المدونة

Incremental Static Regeneration — تبني مرة، وتضل محدث

وقت القراءة 5 دقيقةAR
ISRNext.jsPerformanceCaching

Incremental Static Regeneration — Build Once, Stay Fresh

لو قريت بوستات SSG و SSR بهالمدونة، أنت تعرف المقايضة أصلاً: الصفحات الثابتة سريعة بس تصير قديمة، والصفحات اللي تترندر بالسيرفر محدثة بس أبطأ. ISR موجود حتى يسد هالفجوة. خلنا نتتبع بالضبط شنو يصير من وقت الـ build لحد لحظة ما تتحدث الصفحة بالإنتاج.


الخطوة 1 — التوليد وقت الـ Build

وقت الـ build، Next.js يولّد الصفحة زي ما يسويها لـ SSG — باستخدام أي بيانات متوفرة بهيچ لحظة — ويحفظها كـ HTML ثابت.

// app/products/[id]/page.tsx
export async function generateStaticParams() {
  const products = await db.products.findMany()
  return products.map(product => ({ id: product.id }))
}

export const revalidate = 60 // seconds

export default async function ProductPage({ params }) {
  const product = await db.products.findUnique({
    where: { id: params.id },
  })

  return (
    <main>
      <h1>{product.name}</h1>
      <p>${product.price}</p>
    </main>
  )
}

لاحظ export const revalidate = 60. هذا السطر الوحيد هو اللي يحول SSG العادي إلى ISR.


الخطوة 2 — تحديد نافذة الـ Revalidate

قيمة revalidate تخبر Next.js شقد وقت الصفحة المولّدة مسموحلها تضل "محدثة" قبل ما تصير قديمة. خلال هالنافذة، كل زائر ياخذ نفس الـ HTML المخزن بالكاش — بدون أي شغل بالسيرفر، بدون أي طلب لقاعدة البيانات.

Page built at t=0
        ↓
revalidate: 60
        ↓
Page is "fresh" until t=60s
        ↓
After t=60s, page becomes "stale" (but still served)

قديمة لا تعني معطلة — تعني إن الطلب الجاي راح يفعّل إعادة بناء بالخلفية.


الخطوة 3 — تقديم النسخة المخزنة بالكاش

كل طلب يوصل خلال النافذة المحدثة يتقدم مباشرة من الكاش. هذا مطابق تماماً بالسرعة للتوليد الثابت العادي — ما كو فرق ملموس بالنسبة للمستخدم.

<!-- Served instantly from cache, no compute -->
<main>
  <h1>Mechanical Keyboard</h1>
  <p>$129.00</p>
</main>

هذا الجزء اللي الناس كثير تفوته عن ISR: أغلب الطلبات أصلاً ما تفعّل أي منطق بالسيرفر.


الخطوة 4 — إعادة التوليد بالخلفية

بمجرد ما تنتهي نافذة الـ revalidate، الطلب الجاي اللي يوصل هو المحفّز. هذا الطلب:

  1. ياخذ الـ HTML الموجود (القديم) فوراً — بدون انتظار.
  2. يفعّل إعادة توليد الصفحة بالخلفية باستخدام بيانات محدثة.
Request arrives after t=60s
        ↓
Stale HTML returned immediately (fast)
        ↓
Next.js regenerates the page in the background
        ↓
New HTML written to cache once ready

الزائر اللي فعّل إعادة التوليد ما يشوف أي حالة تحميل. بس يشوف النسخة القديمة — مرة وحدة أخيرة.


الخطوة 5 — التبديل وتقديم النسخة المحدثة

بمجرد ما تخلص إعادة التوليد، الـ HTML الجديد يستبدل القديم بالكاش. كل طلب بعد هالنقطة ياخذ النسخة المحدثة، بنفس سرعة التوليد الثابت.

// Same route, same code — the data underneath just changed
const product = await db.products.findUnique({
  where: { id: params.id },
})
// price updated in the DB → reflected after the next regeneration cycle

بدون إعادة نشر. بدون إعادة بناء كاملة. الصفحة تلحق بالواقع بهدوء.


ISR مقابل SSG مقابل SSR

يحتاج إعادة بناء؟الحداثةالسرعة
SSGإي، إعادة بناء كاملةبس بقدر آخر نشرالأسرع
ISRلا — يصلح نفسه لكل صفحةمحدثة خلال نافذة الـ revalidateنفس SSG
SSRغير مطبق — يشتغل بكل طلبمحدثة دايماًالأبطأ (حساب لكل طلب)

ISR أساساً هو SSG بس بتاريخ انتهاء صلاحية. تاخذ سرعة الملفات الثابتة، والصفحات تعيد بناء نفسها بهدوء بدون ما تلمس أي pipeline نشر.

بـ Next.js App Router:

  • export const revalidate = <seconds> — تحديث معتمد على الوقت
  • revalidatePath("/products/123") — تحديث عند الطلب، مثلاً بعد webhook
  • بدون revalidate أبداً — يصير ثابت بالكامل افتراضياً (زي SSG)

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

تصور هالمدونة عندها صفحة "المنشورات الرائجة" مرتبة حسب عدد المشاهدات. إعادة بناء كل الموقع كل مرة يتغير فيها عدد المشاهدات راح تكون مضيعة. بـ revalidate: 300، صفحة الترتيب تعيد توليد نفسها كل 5 دقايق كحد أقصى — رخيصة، سريعة، وقريبة كفاية من الوقت الفعلي لهالاستخدام.


متى ISR مو الخيار الصح

  • بيانات فعلية بالوقت الحقيقي (أسعار أسهم، نتائج مباشرة) — نافذة القِدم راح تبين أرقام غلط، حتى لو لحظياً. استخدم SSR أو client-side polling بدلها.
  • صفحات خاصة بكل مستخدم (dashboards، سلات تسوق) — كاش ISR مشترك بين كل الزوار. لو المحتوى يختلف حسب المستخدم، ISR الأداة الغلط.
  • صفحات بزيارات قليلة جداً — المقايضة "أول زائر بعد انتهاء الصلاحية ياخذ محتوى قديم" بس تستاهل لو الزيارات كافية تخلي إعادة توليد الكاش مفيدة.

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

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

الخيار الغلط يكلفك إما الأداء، أو الحداثة، أو إعادة بناء غير ضرورية. ISR موجود بالضبط لهالمنطقة الوسطى: محتوى يتغير، بس مو كل ثانية.