المشكلة: متى نُولّد HTML؟
عندما يطلب المستخدم صفحة، يمكن لخادمك توليد HTML في ثلاث لحظات مختلفة:
- وقت الطلب (SSR) — كل زيارة = توليد جديد
- وقت البناء (SSG) — مرّة واحدة، يُخزّن ويُخدم كملف ثابت
- هجين (ISR) — ثابت بالبداية، يُعاد توليده دورياً
كل خيار له مقايضات. نُفصّلها.
1. SSG — Static Site Generation
كيف يعمل؟
عند تشغيل next build، يُولّد Next.js ملف HTML لكل صفحة. عندما يزور المستخدم الصفحة، يصله الـ HTML الجاهز فوراً من CDN.
مثال
// app/about/page.tsx
// هذه الصفحة تُولَّد مرّة واحدة وقت البناء
export default function AboutPage() {
return <h1>من نحن</h1>;
}بيانات ثابتة؟ اجلبها وقت البناء:
export default async function BlogList() {
// يُنفَّذ وقت البناء فقط
const posts = await fetch("https://cms.example.com/posts")
.then(r => r.json());
return (
<ul>
{posts.map(p => <li key={p.id}>{p.title}</li>)}
</ul>
);
}متى نختاره؟
- المدوّنات — المحتوى لا يتغيّر كل ثانية
- صفحات التسويق (landing pages)
- الوثائق التقنية
- المواقع الشخصية
الإيجابيات
- أسرع تجربة ممكنة — HTML جاهز من CDN
- تكلفة استضافة منخفضة — لا حسابات في وقت الطلب
- SEO ممتاز — محركات البحث ترى محتوى فوراً
السلبيات
- وقت بناء طويل مع آلاف الصفحات
- المحتوى يتطلّب إعادة بناء عند التحديث
2. SSR — Server-Side Rendering
كيف يعمل؟
كل زيارة تُنفّذ الكود على الخادم، يُولّد HTML، ويُرسل.
مثال
// يُعاد التقييم كل طلب
export const dynamic = "force-dynamic";
export default async function Dashboard() {
// تُنفَّذ في كل زيارة
const user = await getCurrentUser();
const stats = await fetchLiveStats();
return (
<div>
<h1>أهلاً {user.name}</h1>
<p>الزوار الآن: {stats.active}</p>
</div>
);
}متى نختاره؟
- لوحات تحكم شخصية (تختلف لكل مستخدم)
- نتائج البحث المباشر
- أسعار في الوقت الحقيقي
- صفحات محميّة بتسجيل دخول
الإيجابيات
- بيانات حديثة دائماً
- تخصيص لكل مستخدم
- لا حاجة لإعادة بناء
السلبيات
- أبطأ من SSG (حساب في كل طلب)
- حمل أعلى على الخادم
- تكلفة استضافة أعلى
3. ISR — Incremental Static Regeneration
كيف يعمل؟
هجين ذكي:
- الصفحة تُولَّد ثابتاً وقت البناء (كـ SSG)
- بعد مدّة محدّدة (مثل 60 ثانية)، تُعاد عند أول زيارة
- زيارات أخرى خلال المدّة تصلها النسخة الثابتة
مثال
export const revalidate = 60; // ثانية
export default async function NewsPage() {
const articles = await fetch("https://api.news.com/latest")
.then(r => r.json());
return (
<ul>
{articles.map(a => <li key={a.id}>{a.title}</li>)}
</ul>
);
}متى نختاره؟
- المتاجر الإلكترونية (أسعار/مخزون يتحدّث بطيئاً)
- مواقع الأخبار (تحديث كل بضع دقائق)
- مدوّنة بمحتوى كثير (تحديث كل ساعة)
الإيجابيات
- سرعة SSG معظم الوقت
- تحديث تلقائي بدون إعادة بناء
- أفضل توازن للأغلبية
السلبيات
- قد يرى بعض المستخدمين محتوى قديماً خلال نافذة التحديث
- معقّد قليلاً للإعداد الأوّلي
جدول المقارنة
| المعيار | SSG | SSR | ISR | |---------|-----|-----|-----| | وقت التوليد | البناء | كل طلب | البناء + دوري | | السرعة للمستخدم | ⚡⚡⚡ | ⚡ | ⚡⚡ | | حداثة البيانات | ❌ ثابت | ✅ فورية | ⚠️ دورية | | تكلفة الاستضافة | أرخص | أغلى | متوسّط | | SEO | ✅ | ✅ | ✅ | | إعادة البناء | دائماً | أبداً | أحياناً |
كيف تختار؟
اسأل نفسك ثلاثة أسئلة:
1. هل المحتوى يختلف لكل مستخدم؟ نعم → SSR | لا → استمر
2. هل تحتمل تأخّر دقائق في التحديث؟ نعم → ISR | لا → SSR
3. هل المحتوى ثابت تقريباً؟ نعم → SSG | لا → ISR
مثال: موقع متجر
- الصفحة الرئيسية: ISR كل ساعة (منتجات جديدة أحياناً)
- صفحة المنتج: ISR كل 10 دقائق (سعر/مخزون)
- السلّة: SSR (تختلف لكل مستخدم)
- حساب المستخدم: SSR
- صفحة About/Terms: SSG (لا تتغيّر)
الأسئلة الشائعة
هل يمكن خلطها في مشروع واحد؟
نعم — هذه قوّة Next.js. كل صفحة تختار استراتيجيّتها.
ماذا عن CSR (Client-Side Rendering)؟
هو ما يحدث في React عادي — JavaScript يُولّد HTML في المتصفّح. سيّء للـ SEO وبطيء لأول تحميل. Next.js يتجاوزه لمعظم الصفحات.
ISR و fetch cache؟
ISR يعتمد على cache fetch. لتحكّم دقيق:
fetch("https://api.com/data", {
next: { revalidate: 3600 } // ساعة
});مقالات ذات صلة
بناء REST API كامل بـ Node.js و Express: مشروع عملي
اصنع REST API جاهز للإنتاج بـ Node.js — CRUD كامل، معالجة أخطاء، التحقّق من البيانات، وربط PostgreSQL.
حل مشكلة CORS في Express: الدليل العملي الكامل
واجهت خطأ CORS في تطبيق Node.js؟ تعلّم ما هو، لماذا يحدث، وكيف تُصلحه بطريقة صحيحة (ليس بفتح كل شيء).
React Hooks: شرح useState و useEffect بأمثلة عملية
دليل عملي لأهم hooks في React: useState لإدارة الحالة و useEffect للتعامل مع الآثار الجانبية. أمثلة كاملة بدون حشو.