Incremental Static Regeneration — تبني مرة، وتضل محدث
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، الطلب الجاي اللي يوصل هو المحفّز. هذا الطلب:
- ياخذ الـ HTML الموجود (القديم) فوراً — بدون انتظار.
- يفعّل إعادة توليد الصفحة بالخلفية باستخدام بيانات محدثة.
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 موجود بالضبط لهالمنطقة الوسطى: محتوى يتغير، بس مو كل ثانية.