التحديث التدريجي للصفحات الثابتة (ISR)
يسمح لك Next.js بإنشاء أو تحديث الصفحات الثابتة بعد بناء موقعك. يتيح لك التحديث التدريجي للصفحات الثابتة (ISR) استخدام التوليد الثابت على أساس كل صفحة، دون الحاجة إلى إعادة بناء الموقع بالكامل. مع ISR، يمكنك الاحتفاظ بمزايا التوليد الثابت مع التوسع إلى ملايين الصفحات.
معلومة مفيدة: وقت التشغيل
edge
غير متوافق حاليًا مع ISR، على الرغم من أنه يمكنك الاستفادة منstale-while-revalidate
عن طريق تعيين رأسcache-control
يدويًا.
لاستخدام ISR، أضف خاصية revalidate
إلى getStaticProps
:
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
// يتم استدعاء هذه الدالة أثناء البناء على جانب الخادم.
// قد يتم استدعاؤها مرة أخرى، على دالة بدون خادم، إذا
// تم تمكين إعادة التحقق وجاء طلب جديد
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// سيحاول Next.js إعادة توليد الصفحة:
// - عند وصول طلب جديد
// - على الأكثر مرة كل 10 ثوانٍ
revalidate: 10, // بالثواني
}
}
// يتم استدعاء هذه الدالة أثناء البناء على جانب الخادم.
// قد يتم استدعاؤها مرة أخرى، على دالة بدون خادم، إذا
// لم يتم توليد المسار بعد.
export async function getStaticPaths() {
const res = await fetch('https://.../posts')
const posts = await res.json()
// الحصول على المسارات التي نريد تقديمها مسبقًا بناءً على المنشورات
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// سنقوم بتقديم هذه المسارات مسبقًا فقط أثناء البناء.
// { fallback: 'blocking' } سيقدم الصفحات على الخادم
// عند الطلب إذا لم يكن المسار موجودًا.
return { paths, fallback: 'blocking' }
}
export default Blog
عند إجراء طلب إلى صفحة تم تقديمها مسبقًا أثناء البناء، سيتم عرض النسخة المخزنة مسبقًا.
- أي طلبات للصفحة بعد الطلب الأولي وقبل مرور 10 ثوانٍ سيتم تخزينها أيضًا وتكون فورية.
- بعد نافذة الـ 10 ثوانٍ، سيظل الطلب التالي يعرض الصفحة المخزنة (القديمة)
- يقوم Next.js بتشغيل إعادة توليد الصفحة في الخلفية.
- بمجرد اكتمال توليد الصفحة بنجاح، سيقوم Next.js بإبطال التخزين المؤقت وعرض الصفحة المحدثة. إذا فشل التوليد في الخلفية، ستظل الصفحة القديمة دون تغيير.
عند إجراء طلب إلى مسار لم يتم توليده بعد، سيقوم Next.js بتقديم الصفحة على الخادم عند الطلب الأول. ستخدم الطلبات المستقبلية الملف الثابت من التخزين المؤقت. يحافظ ISR على Vercel على التخزين المؤقت عالميًا ويتعامل مع التراجعات.
معلومة مفيدة: تحقق مما إذا كان مزود البيانات المنبع لديك قد مكّن التخزين المؤقت افتراضيًا. قد تحتاج إلى تعطيله (مثل
useCdn: false
)، وإلا لن تتمكن إعادة التحقق من سحب بيانات جديدة لتحديث تخزين ISR المؤقت. يمكن أن يحدث التخزين المؤقت على CDN (لنقطة النهاية المطلوبة) عندما يعيد رأسCache-Control
.
إعادة التحقق عند الطلب
إذا قمت بتعيين وقت revalidate
إلى 60
، سيرى جميع الزوار نفس النسخة المولدة من موقعك لمدة دقيقة واحدة. الطريقة الوحيدة لإبطال التخزين المؤقت هي من خلال زيارة شخص ما لتلك الصفحة بعد مرور الدقيقة.
بدءًا من الإصدار v12.2.0
، يدعم Next.js التحديث التدريجي للصفحات الثابتة عند الطلب لمسح التخزين المؤقت لـ Next.js يدويًا لصفحة معينة. وهذا يسهل تحديث موقعك عندما:
- يتم إنشاء محتوى جديد أو تحديثه من نظام إدارة المحتوى (CMS)
- تتغير بيانات التجارة الإلكترونية (السعر، الوصف، الفئة، التقييمات، إلخ.)
داخل getStaticProps
، لا تحتاج إلى تحديد revalidate
لاستخدام إعادة التحقق عند الطلب. إذا تم حذف revalidate
، سيستخدم Next.js القيمة الافتراضية false
(لا إعادة تحقق) وسيعيد التحقق من الصفحة عند الطلب فقط عند استدعاء revalidate()
.
معلومة مفيدة: لن يتم تنفيذ البرمجيات الوسيطة لطلبات ISR عند الطلب. بدلاً من ذلك، استدعِ
revalidate()
على المسار الدقيق الذي تريد إعادة التحقق منه. على سبيل المثال، إذا كان لديكpages/blog/[slug].js
وإعادة توجيه من/post-1
->/blog/post-1
، فستحتاج إلى استدعاءres.revalidate('/blog/post-1')
.
استخدام إعادة التحقق عند الطلب
أولاً، قم بإنشاء رمز سري يعرفه فقط تطبيق Next.js الخاص بك. سيتم استخدام هذا السر لمنع الوصول غير المصرح به إلى مسار API إعادة التحقق. يمكنك الوصول إلى المسار (إما يدويًا أو باستخدام webhook) باستخدام هيكل URL التالي:
https://<your-site.com>/api/revalidate?secret=<token>
بعد ذلك، أضف السر كـ متغير بيئة إلى تطبيقك. أخيرًا، قم بإنشاء مسار API إعادة التحقق:
export default async function handler(req, res) {
// التحقق من السر للتأكد من أن هذا طلب صالح
if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
return res.status(401).json({ message: 'Invalid token' })
}
try {
// يجب أن يكون هذا المسار الفعلي وليس مسارًا معاد توجيهه
// على سبيل المثال، لـ "/blog/[slug]" يجب أن يكون "/blog/post-1"
await res.revalidate('/path-to-revalidate')
return res.json({ revalidated: true })
} catch (err) {
// إذا كان هناك خطأ، سيستمر Next.js
// في عرض آخر صفحة تم توليدها بنجاح
return res.status(500).send('Error revalidating')
}
}
شاهد العرض التوضيحي لدينا لرؤية إعادة التحقق عند الطلب في العمل وتقديم الملاحظات.
اختبار ISR عند الطلب أثناء التطوير
عند التشغيل محليًا باستخدام next dev
، يتم استدعاء getStaticProps
عند كل طلب. للتحقق من أن تكوين ISR عند الطلب صحيح، ستحتاج إلى إنشاء بناء إنتاج وتشغيل خادم الإنتاج:
$ next build
$ next start
ثم، يمكنك تأكيد أن الصفحات الثابتة قد تم إعادة التحقق منها بنجاح.
التعامل مع الأخطاء وإعادة التحقق
إذا حدث خطأ داخل getStaticProps
عند التعامل مع التوليد في الخلفية، أو إذا قمت برمي خطأ يدويًا، ستستمر الصفحة الأخيرة التي تم توليدها بنجاح في الظهور. في الطلب التالي، سيحاول Next.js استدعاء getStaticProps
مرة أخرى.
export async function getStaticProps() {
// إذا ألقى هذا الطلب خطأ غير معالج، فلن يقوم Next.js
// بإبطال الصفحة المعروضة حاليًا وسيتم
// إعادة محاولة getStaticProps في الطلب التالي.
const res = await fetch('https://.../posts')
const posts = await res.json()
if (!res.ok) {
// إذا كان هناك خطأ في الخادم، قد ترغب في
// إلقاء خطأ بدلاً من الإرجاع حتى لا يتم تحديث التخزين المؤقت
// حتى الطلب الناجح التالي.
throw new Error(`Failed to fetch posts, received status ${res.status}`)
}
// إذا كان الطلب ناجحًا، قم بإرجاع المنشورات
// وإعادة التحقق كل 10 ثوانٍ.
return {
props: {
posts,
},
revalidate: 10,
}
}
الاستضافة الذاتية لـ ISR
يعمل التحديث التدريجي للصفحات الثابتة (ISR) على مواقع Next.js المستضافة ذاتيًا مباشرة عند استخدام next start
.
يمكنك استخدام هذا الأسلوب عند النشر على منسقات الحاويات مثل Kubernetes أو HashiCorp Nomad. افتراضيًا، سيتم تخزين الأصول المولدة في الذاكرة على كل pod. وهذا يعني أن كل pod سيكون لديه نسخته الخاصة من الملفات الثابتة. قد يتم عرض بيانات قديمة حتى يتم الوصول إلى ذلك الـ pod المحدد بواسطة طلب.
لضمان الاتساق عبر جميع الـ pods، يمكنك تعطيل التخزين المؤقت في الذاكرة. سيخبر هذا خادم Next.js بالاعتماد فقط على الأصول المولدة بواسطة ISR في نظام الملفات.
يمكنك استخدام نقطة تركيب شبكة مشتركة في Kubernetes pods (أو إعداد مشابه) لإعادة استخدام نفس تخزين نظام الملفات بين الحاويات المختلفة. بمشاركة نفس نقطة التركيب، سيتم أيضًا مشاركة مجلد .next
الذي يحتوي على تخزين next/image
المؤقت وإعادة استخدامه.
لتعطيل التخزين المؤقت في الذاكرة، قم بتعيين isrMemoryCacheSize
إلى 0
في ملف next.config.js
:
module.exports = {
experimental: {
// القيمة الافتراضية 50MB
isrMemoryCacheSize: 0, // حجم التخزين المؤقت بالبايت
},
}
معلومة مفيدة: قد تحتاج إلى النظر في حالة السباق بين عدة pods تحاول تحديث التخزين المؤقت في نفس الوقت، اعتمادًا على كيفية تكوين نقطة التركيب المشتركة.
سجل الإصدارات
الإصدار | التغييرات |
---|---|
v12.2.0 | أصبح ISR عند الطلب مستقرًا |
v12.1.0 | تمت إضافة ISR عند الطلب (بيتا). |
v12.0.0 | تمت إضافة الاسترجاع باستخدام ISR مع وعي بالروبوتات. |
v9.5.0 | تمت إضافة المسار الأساسي. |