المدونة

Server-Side Rendering — من الطلب إلى HTML

وقت القراءة 4 دقيقةAR
SSRNext.jsPerformanceSEO

Server-Side Rendering — From Request to HTML

Server-Side Rendering وحد من هالمصطلحات اللي تنرمى بكل مكان بس نادراً تنشرح بدقة. خلنا نتتبع بالضبط شنو يصير من لحظة ما المستخدم يضغط Enter بالمتصفح لحد لحظة ما يشوف الصفحة.


الخطوة 1 — الطلب

المستخدم يروح لـ https://yoursite.com/products.

المتصفح يرسل طلب HTTP GET لسيرفرك. بتطبيق Next.js، هذا الطلب يوصل لـ Next.js runtime.


الخطوة 2 — السيرفر يشغّل الـ Component متاعك

مع SSR (أو RSC)، دالة الـ component متاعك تشتغل فعلياً بالسيرفر:

// This runs on the server — not in the browser
export default async function ProductsPage() {
  // This database call happens on the server
  const products = await db.products.findMany({
    orderBy: { createdAt: "desc" },
  })

  return (
    <main>
      <h1>Products</h1>
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </main>
  )
}

لاحظ: async/await مباشرة جوة الـ component. بدون useEffect. بدون حالة تحميل. البيانات موجودة أصلاً قبل ما يتبنى الـ HTML.


الخطوة 3 — React يحوّل لسلسلة HTML

React ياخذ شجرة الـ component متاعك ويحولها لسلسلة نصية HTML بالسيرفر:

<main>
  <h1>Products</h1>
  <div class="product-card">
    <h2>Mechanical Keyboard</h2>
    <p>$129.00</p>
  </div>
  <div class="product-card">
    <h2>USB-C Hub</h2>
    <p>$49.00</p>
  </div>
</main>

هذا HTML حقيقي — مو template بـ JavaScript، مو virtual DOM. ماركب فعلي (actual markup).


الخطوة 4 — المتصفح يستلم HTML كامل

المتصفح ياخذ هذا الـ HTML ويعرضه فوراً. ما يحتاج أي JavaScript يشتغل أول. المستخدم يشوف محتوى.

هذا سبب أهمية SSR لـ:

SEO — Google يزحف (crawl) على HTML. لو صفحتك فاضية لحد ما JS يشتغل، Google ممكن ما يفهرس محتواك صح. مع SSR، الروبوت يشوف نفس اللي يشوفه المستخدم.

الأداء — مقياس First Contentful Paint (FCP) — شقد سريع المستخدم يشوف شي — أحسن بكثير مع SSR. على اتصال 3G، هذا ممكن يكون الفرق بين ثانية وحدة و6 ثواني.

المشاركة الاجتماعية — لما تشارك رابط بتويتر أو تلغرام، الروبوتات متاعهم تقرأ وسوم <meta> من الـ HTML. مع CSR، هالوسوم ممكن ما تكون موجودة لسا وقت ما الروبوت يزور الصفحة.


الخطوة 5 — Hydration

الصفحة تبين صحيحة بس لسا مو تفاعلية. React هسه يحتاج يسوي "hydration" — يربط معالجات أحداث JavaScript بالـ HTML الموجود.

HTML renders in browser (fast)
        ↓
JavaScript bundle downloads
        ↓
React reconciles virtual DOM with real DOM
        ↓
Event listeners attached — page is interactive

هذا العيب الوحيد بـ SSR: فيه نافذة قصيرة الصفحة تبين تفاعلية بس مو فعلاً. الضغط على زر ممكن ما يشتغل لثانية أو ثانيتين.

React Server Components تحل هذا جزئياً — الـ components اللي ما تحتاج تفاعلية أصلاً ما تسوي hydration.


SSR مقابل التوليد الثابت

SSR يشتغل بكل طلب. بس أحياناً ما تحتاج هذا.

Static Site Generation (SSG) يعرض الصفحات وقت الـ build — مرة وحدة — ويقدم الـ HTML المخزن للكل. ممتاز لمنشورات المدونة، التوثيق، والصفحات اللي محتواها ما يتغير حسب المستخدم.

// SSG — runs once at build time
export async function generateStaticParams() {
  const posts = await getAllPosts()
  return posts.map(post => ({ slug: post.slug }))
}

SSR — يشتغل بكل طلب. ضروري لما الصفحة تعتمد على المستخدم (سلته، بروفايله، فيده).

بـ Next.js App Router:

  • الافتراضي: ثابت (يترندر وقت الـ build)
  • ضيف export const dynamic = "force-dynamic" لـ SSR بكل طلب
  • ضيف fetch() بدون خيارات كاش حتى تختار الرندر الديناميكي

مثال حقيقي من هذا الموقع

بوست المدونة اللي تقره هسه مولّد بشكل ثابت. وقت الـ build، Next.js يقرأ ملف .mdx، يعرضه لـ HTML، وهذا الـ HTML يتقدم لكل زائر فوراً — بدون أي معالجة بالسيرفر بكل طلب.

المقايضة: لو حدّثت البوست، أحتاج أعيد النشر. لمدونة شخصية، هذا شي عادي تماماً.


متى تستخدم شنو

السيناريوالاستراتيجية
منشورات المدونة، التوثيقثابت (SSG)
الصفحات التسويقيةثابت (SSG)
لوحة تحكم المستخدمSSR أو Client
صفحة منتج بمتجر إلكترونيSSR (للأسعار المباشرة)
فيد بالوقت الحقيقيClient-side
نتائج البحثSSR

الخيار الغلط يكلفك إما الأداء (كثير JavaScript على جهة العميل) أو الحداثة (صفحات ثابتة قديمة). اعرف بياناتك — بعدين اختار.