التخزين المؤقت في Next.js
يحسن Next.js أداء تطبيقك ويقلل التكاليف عن طريق تخزين أعمال التصيير وطلبات البيانات مؤقتًا. توفر هذه الصفحة نظرة متعمقة على آليات التخزين المؤقت في Next.js، وواجهات برمجة التطبيقات (APIs) التي يمكنك استخدامها لتكوينها، وكيفية تفاعلها مع بعضها البعض.
معلومة مفيدة: هذه الصفحة تساعدك على فهم كيفية عمل Next.js تحت الغطاء ولكنها ليست معرفة أساسية لتكون منتجًا باستخدام Next.js. يتم تحديد معظم استدلالات التخزين المؤقت في Next.js من خلال استخدامك لواجهة برمجة التطبيقات ولها إعدادات افتراضية لأفضل أداء مع تكوين صفري أو ضئيل.
نظرة عامة
إليك نظرة عامة عالية المستوى على آليات التخزين المؤقت المختلفة والغرض منها:
الآلية | ماذا | أين | الغرض | المدة |
---|---|---|---|---|
تخزين الطلبات مؤقتًا | قيم الإرجاع للوظائف | الخادم | إعادة استخدام البيانات في شجرة مكونات React | دورة حياة الطلب |
ذاكرة التخزين المؤقت للبيانات | البيانات | الخادم | تخزين البيانات عبر طلبات المستخدم والنشرات | دائمة (يمكن إعادة التحقق منها) |
ذاكرة التخزين المؤقت الكاملة للطريق | HTML وحمولة RSC | الخادم | تقليل تكلفة التصيير وتحسين الأداء | دائمة (يمكن إعادة التحقق منها) |
ذاكرة التخزين المؤقت للموجه | حمولة RSC | العميل | تقليل طلبات الخادم أثناء التنقل | جلسة المستخدم أو زمنية |
بشكل افتراضي، سيخزن Next.js أكبر قدر ممكن لتحسين الأداء وتقليل التكلفة. هذا يعني أن الطرق يتم تصييرها بشكل ثابت وطلبات البيانات مخزنة مؤقتًا إلا إذا اخترت عدم ذلك. يوضح الرسم البياني أدناه سلوك التخزين المؤقت الافتراضي: عندما يتم تصيير طريق بشكل ثابت في وقت البناء وعند زيارة طريق ثابت لأول مرة.

يتغير سلوك التخزين المؤقت اعتمادًا على ما إذا كان الطريق يتم تصييره بشكل ثابت أو ديناميكي، وما إذا كانت البيانات مخزنة مؤقتًا أو غير مخزنة، وما إذا كان الطلب جزءًا من زيارة أولية أو تنقل لاحق. اعتمادًا على حالة الاستخدام الخاصة بك، يمكنك تكوين سلوك التخزين المؤقت لطرق وطلبات بيانات فردية.
تخزين الطلبات مؤقتًا (Request Memoization)
يمتد React واجهة برمجة التطبيقات fetch
لتخزين الطلبات التي لها نفس URL والخيارات تلقائيًا مؤقتًا. هذا يعني أنه يمكنك استدعاء دالة fetch لنفس البيانات في أماكن متعددة في شجرة مكونات React مع تنفيذها مرة واحدة فقط.

على سبيل المثال، إذا كنت بحاجة إلى استخدام نفس البيانات عبر طريق (مثل في Layout و Page ومكونات متعددة)، لا يتعين عليك جلب البيانات في أعلى الشجرة، وإعادة توجيه الخصائص بين المكونات. بدلاً من ذلك، يمكنك جلب البيانات في المكونات التي تحتاجها دون القلق بشأن الآثار المترتبة على الأداء لإنشاء طلبات متعددة عبر الشبكة لنفس البيانات.
async function getItem() {
// يتم تخزين دالة `fetch` تلقائيًا مؤقتًا والنتيجة
// مخزنة مؤقتًا
const res = await fetch('https://.../item/1')
return res.json()
}
// يتم استدعاء هذه الدالة مرتين، ولكن يتم تنفيذها فقط في المرة الأولى
const item = await getItem() // cache MISS
// يمكن أن يكون الاستدعاء الثاني في أي مكان في طريقك
const item = await getItem() // cache HIT
async function getItem() {
// يتم تخزين دالة `fetch` تلقائيًا مؤقتًا والنتيجة
// مخزنة مؤقتًا
const res = await fetch('https://.../item/1')
return res.json()
}
// يتم استدعاء هذه الدالة مرتين، ولكن يتم تنفيذها فقط في المرة الأولى
const item = await getItem() // cache MISS
// يمكن أن يكون الاستدعاء الثاني في أي مكان في طريقك
const item = await getItem() // cache HIT
كيف يعمل تخزين الطلبات مؤقتًا

- أثناء تصيير طريق، عند استدعاء طلب معين لأول مرة، لن تكون نتيجته في الذاكرة وسيكون cache
MISS
. - لذلك، سيتم تنفيذ الدالة، وسيتم جلب البيانات من المصدر الخارجي، وسيتم تخزين النتيجة في الذاكرة.
- استدعاءات الدالة اللاحقة للطلب في نفس تمرير التصيير ستكون cache
HIT
، وسيتم إرجاع البيانات من الذاكرة دون تنفيذ الدالة. - بمجرد اكتمال تصيير الطريق وتمرير التصيير، يتم "إعادة تعيين" الذاكرة ومسح جميع إدخالات تخزين الطلبات مؤقتًا.
معلومة مفيدة:
- تخزين الطلبات مؤقتًا هو ميزة React وليست ميزة Next.js. تم تضمينها هنا لإظهار كيفية تفاعلها مع آليات التخزين المؤقت الأخرى.
- التخزين المؤقت ينطبق فقط على طريقة
GET
في طلباتfetch
.- التخزين المؤقت ينطبق فقط على شجرة مكونات React، وهذا يعني:
- ينطبق على طلبات
fetch
فيgenerateMetadata
وgenerateStaticParams
و Layouts و Pages ومكونات الخادم الأخرى.- لا ينطبق على طلبات
fetch
في Route Handlers لأنها ليست جزءًا من شجرة مكونات React.- للحالات التي لا تكون فيها
fetch
مناسبة (مثل بعض عملاء قواعد البيانات أو عملاء CMS أو عملاء GraphQL)، يمكنك استخدام دالةcache
في React لتخزين الدوال مؤقتًا.
المدة
يستمر التخزين المؤقت طوال مدة طلب الخادم حتى تنتهي شجرة مكونات React من التصيير.
إعادة التحقق
نظرًا لأن التخزين المؤقت لا يتم مشاركته عبر طلبات الخادم وينطبق فقط أثناء التصيير، فلا حاجة لإعادة التحقق منه.
عدم المشاركة
ينطبق التخزين المؤقت فقط على طريقة GET
في طلبات fetch
، ولا يتم تخزين الطرق الأخرى مثل POST
و DELETE
مؤقتًا. هذا السلوك الافتراضي هو تحسين من React ولا نوصي بعدم المشاركة فيه.
لإدارة الطلبات الفردية، يمكنك استخدام خاصية signal
من AbortController
. ومع ذلك، هذا لن يؤدي إلى عدم تخزين الطلبات مؤقتًا، بل سيؤدي إلى إلغاء الطلبات الجارية.
const { signal } = new AbortController()
fetch(url, { signal })
ذاكرة التخزين المؤقت للبيانات (Data Cache)
يحتوي Next.js على ذاكرة تخزين مؤقت مدمجة للبيانات تحافظ على نتيجة جلب البيانات عبر طلبات الخادم الواردة والنشرات. هذا ممكن لأن Next.js يمتد واجهة برمجة التطبيقات fetch
الأصلية للسماح لكل طلب على الخادم بتعيين دلالات التخزين المؤقت الخاصة به.
معلومة مفيدة: في المتصفح، يشير خيار
cache
لـfetch
إلى كيفية تفاعل الطلب مع ذاكرة التخزين المؤقت HTTP للمتصفح، في Next.js، يشير خيارcache
إلى كيفية تفاعل طلب الخادم مع ذاكرة التخزين المؤقت للبيانات على الخادم.
بشكل افتراضي، يتم تخزين طلبات البيانات التي تستخدم fetch
مؤقتًا. يمكنك استخدام خيارات cache
و next.revalidate
لـ fetch
لتكوين سلوك التخزين المؤقت.
كيف تعمل ذاكرة التخزين المؤقت للبيانات

- عند استدعاء طلب
fetch
لأول مرة أثناء التصيير، يتحقق Next.js من ذاكرة التخزين المؤقت للبيانات بحثًا عن استجابة مخزنة. - إذا تم العثور على استجابة مخزنة، يتم إرجاعها على الفور وتخزينها مؤقتًا.
- إذا لم يتم العثور على استجابة مخزنة، يتم إجراء الطلب إلى مصدر البيانات، وتخزين النتيجة في ذاكرة التخزين المؤقت للبيانات، وتخزينها مؤقتًا.
- بالنسبة للبيانات غير المخزنة (مثل
{ cache: 'no-store' }
)، يتم دائمًا جلب النتيجة من مصدر البيانات، وتخزينها مؤقتًا. - سواء كانت البيانات مخزنة أو غير مخزنة، يتم دائمًا تخزين الطلبات مؤقتًا لتجنب إنشاء طلبات مكررة لنفس البيانات أثناء تمرير تصيير React.
الاختلافات بين ذاكرة التخزين المؤقت للبيانات وتخزين الطلبات مؤقتًا
بينما تساعد آليتا التخزين المؤقت في تحسين الأداء عن طريق إعادة استخدام البيانات المخزنة مؤقتًا، فإن ذاكرة التخزين المؤقت للبيانات تدوم عبر الطلبات الواردة والنشرات، بينما يدوم التخزين المؤقت فقط طوال مدة الطلب.
مع التخزين المؤقت، نقلل عدد الطلبات المكررة في نفس تمرير التصيير التي يجب أن تعبر حدود الشبكة من خادم التصيير إلى خادم ذاكرة التخزين المؤقت للبيانات (مثل CDN أو Edge Network) أو مصدر البيانات (مثل قاعدة بيانات أو CMS). مع ذاكرة التخزين المؤقت للبيانات، نقلل عدد الطلبات الموجهة إلى مصدر البيانات الأصلي.
المدة
ذاكرة التخزين المؤقت للبيانات تدوم عبر الطلبات الواردة والنشرات ما لم تقم بإعادة التحقق أو عدم المشاركة.
إعادة التحقق
يمكن إعادة التحقق من البيانات المخزنة مؤقتًا بطريقتين، باستخدام:
- إعادة التحقق الزمنية: إعادة التحقق من البيانات بعد مرور فترة زمنية معينة وإجراء طلب جديد. هذا مفيد للبيانات التي تتغير نادرًا وليست الحداثة فيها حرجة.
- إعادة التحقق عند الطلب: إعادة التحقق من البيانات بناءً على حدث (مثل تقديم نموذج). يمكن أن تستخدم إعادة التحقق عند الطلب نهجًا يعتمد على العلامات أو المسار لإعادة التحقق من مجموعات البيانات دفعة واحدة. هذا مفيد عندما تريد التأكد من عرض أحدث البيانات في أسرع وقت ممكن (مثل عند تحديث المحتوى من نظام إدارة المحتوى الخاص بك).
إعادة التحقق الزمنية
لإعادة التحقق من البيانات على فترات زمنية، يمكنك استخدام خيار next.revalidate
لـ fetch
لتعيين عمر ذاكرة التخزين المؤقت للمورد (بالثواني).
// إعادة التحقق على الأكثر كل ساعة
fetch('https://...', { next: { revalidate: 3600 } })
بدلاً من ذلك، يمكنك استخدام خيارات تكوين قطاع الطريق لتكوين جميع طلبات fetch
في قطاع أو للحالات التي لا يمكنك فيها استخدام fetch
.
كيف تعمل إعادة التحقق الزمنية

- عند استدعاء طلب fetch مع
revalidate
لأول مرة، سيتم جلب البيانات من مصدر البيانات الخارجي وتخزينها في ذاكرة التخزين المؤقت للبيانات. - أي طلبات يتم استدعاؤها خلال الإطار الزمني المحدد (مثل 60 ثانية) سترجع البيانات المخزنة.
- بعد الإطار الزمني، سيظل الطلب التالي يرجع البيانات المخزنة (القديمة الآن).
- سيؤدي Next.js إلى إعادة التحقق من البيانات في الخلفية.
- بمجرد جلب البيانات بنجاح، سيحدث Next.js ذاكرة التخزين المؤقت للبيانات بالبيانات الجديدة.
- إذا فشلت إعادة التحقق في الخلفية، سيتم الاحتفاظ بالبيانات السابقة دون تغيير.
هذا مشابه لسلوك stale-while-revalidate.
إعادة التحقق عند الطلب
يمكن إعادة التحقق من البيانات عند الطلب عن طريق المسار (revalidatePath
) أو عن طريق علامة ذاكرة التخزين المؤقت (revalidateTag
).
كيف تعمل إعادة التحقق عند الطلب

- عند استدعاء طلب
fetch
لأول مرة، سيتم جلب البيانات من مصدر البيانات الخارجي وتخزينها في ذاكرة التخزين المؤقت للبيانات. - عند تشغيل إعادة التحقق عند الطلب، سيتم مسح إدخالات ذاكرة التخزين المؤقت المناسبة من الذاكرة المؤقتة.
- يختلف هذا عن إعادة التحقق الزمنية، التي تحتفظ بالبيانات القديمة في الذاكرة المؤقتة حتى يتم جلب البيانات الجديدة.
- في المرة التالية التي يتم فيها إجراء طلب، سيكون cache
MISS
مرة أخرى، وسيتم جلب البيانات من مصدر البيانات الخارجي وتخزينها في ذاكرة التخزين المؤقت للبيانات.
عدم المشاركة
لطلبات جلب البيانات الفردية، يمكنك عدم المشاركة في التخزين المؤقت عن طريق تعيين خيار cache
إلى no-store
. هذا يعني أنه سيتم جلب البيانات كلما تم استدعاء fetch
.
// عدم المشاركة في التخزين المؤقت لطلب `fetch` فردي
fetch(`https://...`, { cache: 'no-store' })
بدلاً من ذلك، يمكنك أيضًا استخدام خيارات تكوين قطاع الطريق لعدم المشاركة في التخزين المؤقت لقطاع طريق معين. سيؤثر هذا على جميع طلبات البيانات في قطاع الطريق، بما في ذلك مكتبات الطرف الثالث.
// عدم المشاركة في التخزين المؤقت لجميع طلبات البيانات في قطاع الطريق
export const dynamic = 'force-dynamic'
ملاحظة: ذاكرة التخزين المؤقت للبيانات متاحة حاليًا فقط في الصفحات/الطرق، وليس في middleware. أي عمليات جلب تتم داخل middleware الخاص بك ستكون غير مخزنة افتراضيًا.
ذاكرة التخزين المؤقت للبيانات في Vercel
إذا تم نشر تطبيق Next.js الخاص بك على Vercel، نوصي بقراءة وثائق ذاكرة التخزين المؤقت للبيانات في Vercel لفهم أفضل للميزات الخاصة بـ Vercel.
ذاكرة التخزين المؤقت الكاملة للطريق (Full Route Cache)
المصطلحات ذات الصلة:
قد ترى مصطلحات التحسين الثابت التلقائي أو توليد الموقع الثابت أو التصيير الثابت تُستخدم بالتبادل للإشارة إلى عملية تصيير وتخزين طرق تطبيقك مؤقتًا في وقت البناء.
يُصيِّر Next.js ويخزن الطرق مؤقتًا تلقائيًا في وقت البناء. هذا تحسين يسمح لك بتقديم الطريق المخزن مؤقتًا بدلاً من التصيير على الخادم لكل طلب، مما يؤدي إلى تحميل أسرع للصفحات.
لفهم كيفية عمل ذاكرة التخزين المؤقت الكاملة للطريق، من المفيد النظر في كيفية تعامل React مع التصيير، وكيف يخزن Next.js النتيجة:
1. تصيير React على الخادم
على الخادم، يستخدم Next.js واجهات برمجة تطبيقات React لتنظيم التصيير. يتم تقسيم عمل التصيير إلى أجزاء: حسب أجزاء الطريق الفردية وحدود Suspense.
يتم تصيير كل جزء في خطوتين:
- يُصيِّر React مكونات الخادم إلى تنسيق بيانات خاص مُحسَّن للبث، يُسمى React Server Component Payload.
- يستخدم Next.js React Server Component Payload وتعليمات JavaScript لمكونات العميل لتصيير HTML على الخادم.
هذا يعني أننا لا نحتاج إلى الانتظار حتى يتم تصيير كل شيء قبل تخزين العمل مؤقتًا أو إرسال استجابة. بدلاً من ذلك، يمكننا بث استجابة أثناء اكتمال العمل.
ما هو React Server Component Payload؟
React Server Component Payload هو تمثيل ثنائي مضغوط لشجرة مكونات خادم React المصيَّرة. يتم استخدامه بواسطة React على العميل لتحديث DOM للمتصفح. يحتوي React Server Component Payload على:
- نتيجة تصيير مكونات الخادم
- عناصر نائبة لمكان تصيير مكونات العميل ومراجع لملفات JavaScript الخاصة بها
- أي خصائص تم تمريرها من مكون خادم إلى مكون عميل
لمعرفة المزيد، راجع وثائق مكونات الخادم.
2. تخزين Next.js مؤقتًا على الخادم (ذاكرة التخزين المؤقت الكاملة للطريق)

السلوك الافتراضي لـ Next.js هو تخزين نتيجة التصيير (React Server Component Payload و HTML) لطريق على الخادم مؤقتًا. ينطبق هذا على الطرق المصيَّرة بشكل ثابت في وقت البناء، أو أثناء إعادة التحقق.
3. التهيئة (Hydration) والمصالحة (Reconciliation) لـ React على العميل
في وقت الطلب، على جانب العميل:
- يتم استخدام HTML لعرض معاينة أولية سريعة غير تفاعلية لمكونات العميل والخادم.
- يتم استخدام حمولة مكونات خادم React (React Server Components Payload) لمصالحة أشجار مكونات العميل ومكونات الخادم المُعَرضة، وتحديث DOM.
- يتم استخدام تعليمات JavaScript لـتهيئة مكونات العميل وجعل التطبيق تفاعليًا.
4. التخزين المؤقت في Next.js على العميل (ذاكرة التوجيه Router Cache)
يتم تخزين حمولة مكونات خادم React في ذاكرة التوجيه على جانب العميل - وهي ذاكرة تخزين مؤقت منفصلة في الذاكرة، مقسمة حسب أجزاء المسار الفردية. تُستخدم ذاكرة التوجيه هذه لتحسين تجربة التنقل عن طريق تخزين المسارات التي تمت زيارتها مسبقًا وجلب المسارات المستقبلية مسبقًا.
5. عمليات التنقل اللاحقة
في عمليات التنقل اللاحقة أو أثناء الجلب المسبق، سيتحقق Next.js مما إذا كانت حمولة مكونات خادم React مخزنة في ذاكرة التوجيه. إذا كانت موجودة، فسيتم تخطي إرسال طلب جديد إلى الخادم.
إذا لم تكن أجزاء المسار موجودة في الذاكرة المؤقتة، فسوف يقوم Next.js بجلب حمولة مكونات خادم React من الخادم، وملء ذاكرة التوجيه على العميل.
العرض الثابت والديناميكي
يعتمد ما إذا كان المسار مخزنًا مؤقتًا في وقت البناء أم لا على ما إذا كان معروضًا بشكل ثابت أو ديناميكي. يتم تخزين المسارات الثابتة مؤقتًا افتراضيًا، بينما يتم عرض المسارات الديناميكية في وقت الطلب ولا يتم تخزينها مؤقتًا.
يوضح هذا الرسم البياني الفرق بين المسارات المعروضة بشكل ثابت وديناميكي، مع البيانات المخزنة مؤقتًا وغير المخزنة:

تعرف على المزيد حول العرض الثابت والديناميكي.
المدة
افتراضيًا، تكون ذاكرة المسار الكاملة دائمة. وهذا يعني أن ناتج العرض يتم تخزينه مؤقتًا عبر طلبات المستخدم.
الإبطال
هناك طريقتان يمكنك من خلالهما إبطال ذاكرة المسار الكاملة:
- إعادة التحقق من البيانات: إعادة التحقق من ذاكرة البيانات سوف يؤدي بدوره إلى إبطال ذاكرة التوجيه عن طريق إعادة عرض المكونات على الخادم وتخزين ناتج العرض الجديد.
- إعادة النشر: على عكس ذاكرة البيانات، التي تظل موجودة عبر عمليات النشر، يتم مسح ذاكرة المسار الكاملة عند عمليات النشر الجديدة.
الانسحاب
يمكنك الانسحاب من ذاكرة المسار الكاملة، أو بعبارة أخرى، عرض المكونات ديناميكيًا لكل طلب وارد، عن طريق:
- استخدام وظيفة ديناميكية: سيؤدي هذا إلى إخراج المسار من ذاكرة المسار الكاملة وعرضه ديناميكيًا في وقت الطلب. لا يزال يمكن استخدام ذاكرة البيانات.
- استخدام خيارات تكوين جزء المسار
dynamic = 'force-dynamic'
أوrevalidate = 0
: سيؤدي هذا إلى تخطي ذاكرة المسار الكاملة وذاكرة البيانات. مما يعني أنه سيتم عرض المكونات وجلب البيانات في كل طلب وارد إلى الخادم. ستظل ذاكرة التوجيه سارية لأنها ذاكرة على جانب العميل. - الانسحاب من ذاكرة البيانات: إذا كان للمسار طلب
fetch
غير مخزن مؤقتًا، فسيؤدي هذا إلى إخراج المسار من ذاكرة المسار الكاملة. سيتم جلب البيانات لطلبfetch
المحدد لكل طلب وارد. سيتم تخزين طلباتfetch
الأخرى التي لا تنسحب من التخزين المؤقت في ذاكرة البيانات. وهذا يسمح بمزيج من البيانات المخزنة وغير المخزنة.
ذاكرة التوجيه (Router Cache)
المصطلحات ذات الصلة:
قد تشاهد الإشارة إلى ذاكرة التوجيه باسم ذاكرة العميل أو ذاكرة الجلب المسبق. بينما تشير ذاكرة الجلب المسبق إلى أجزاء المسار التي تم جلبها مسبقًا، تشير ذاكرة العميل إلى ذاكرة التوجيه بأكملها، والتي تشمل كل من الأجزاء التي تمت زيارتها والتي تم جلبها مسبقًا. هذه الذاكرة المؤقتة تنطبق تحديدًا على Next.js ومكونات الخادم، وهي تختلف عن bfcache في المتصفح، على الرغم من أن لها نتيجة مماثلة.
يحتوي Next.js على ذاكرة تخزين مؤقت على جانب العميل في الذاكرة تقوم بتخزين حمولة مكونات خادم React، مقسمة حسب أجزاء المسار الفردية، طوال مدة جلسة المستخدم. وهذا ما يسمى بذاكرة التوجيه.
كيف تعمل ذاكرة التوجيه

عندما يتنقل المستخدم بين المسارات، يقوم Next.js بتخزين أجزاء المسار التي تمت زيارتها وجلب المسارات التي من المحتمل أن ينتقل إليها المستخدم مسبقًا (بناءً على مكونات <Link>
في نطاق الرؤية).
هذا يؤدي إلى تحسين تجربة التنقل للمستخدم:
- تنقل فوري للخلف/الأمام لأن المسارات التي تمت زيارتها مخزنة مؤقتًا وتنقل سريع إلى المسارات الجديدة بسبب الجلب المسبق والعرض الجزئي.
- لا يوجد إعادة تحميل كاملة للصفحة بين عمليات التنقل، ويتم الحفاظ على حالة React وحالة المتصفح.
الفرق بين ذاكرة التوجيه وذاكرة المسار الكاملة:
تقوم ذاكرة التوجيه بتخزين حمولة مكونات خادم React مؤقتًا في المتصفح طوال مدة جلسة المستخدم، بينما تقوم ذاكرة المسار الكاملة بتخزين حمولة مكونات خادم React و HTML بشكل دائم على الخادم عبر طلبات متعددة للمستخدم.
بينما تقوم ذاكرة المسار الكاملة بتخزين المسارات المعروضة بشكل ثابت فقط، تنطبق ذاكرة التوجيه على كل من المسارات المعروضة بشكل ثابت وديناميكي.
المدة
يتم تخزين الذاكرة المؤقتة في الذاكرة المؤقتة للمتصفح. هناك عاملان يحددان المدة التي تستمر فيها ذاكرة التوجيه:
- الجلسة: تستمر الذاكرة المؤقتة عبر التنقل. ومع ذلك، يتم مسحها عند تحديث الصفحة.
- فترة الإبطال التلقائي: يتم إبطال الذاكرة المؤقتة للتخطيطات وحالات التحميل تلقائيًا بعد وقت محدد. تعتمد المدة على كيفية الجلب المسبق للمورد، وما إذا كان المورد تم إنشاؤه بشكل ثابت:
- الجلب المسبق الافتراضي (
prefetch={null}
أو غير محدد): غير مخزن للمسارات الديناميكية، 5 دقائق للمسارات الثابتة. - الجلب المسبق الكامل (
prefetch={true}
أوrouter.prefetch
): 5 دقائق لكل من المسارات الثابتة والديناميكية.
- الجلب المسبق الافتراضي (
بينما يؤدي تحديث الصفحة إلى مسح جميع الأجزاء المخزنة مؤقتًا، فإن فترة الإبطال التلقائي تؤثر فقط على الجزء الفردي من وقت جلبها مسبقًا.
من الجيد معرفة: يمكن استخدام خيار التكوين التجريبي
staleTimes
لضبط أوقات الإبطال التلقائي المذكورة أعلاه.
الإبطال
هناك طريقتان يمكنك من خلالهما إبطال ذاكرة التوجيه:
- في إجراء خادم (Server Action):
- إعادة التحقق من البيانات حسب الطلب عن طريق المسار باستخدام (
revalidatePath
) أو عن طريق علامة التخزين المؤقت باستخدام (revalidateTag
) - استخدام
cookies.set
أوcookies.delete
يبطل ذاكرة التوجيه لمنع المسارات التي تستخدم ملفات تعريف الارتباط من أن تصبح قديمة (مثل المصادقة).
- إعادة التحقق من البيانات حسب الطلب عن طريق المسار باستخدام (
- استدعاء
router.refresh
سوف يبطل ذاكرة التوجيه ويجعل طلبًا جديدًا إلى الخادم للمسار الحالي.
الانسحاب
ليس من الممكن الانسحاب من ذاكرة التوجيه. ومع ذلك، يمكنك إبطالها عن طريق استدعاء router.refresh
، أو revalidatePath
، أو revalidateTag
(انظر أعلاه). سيؤدي هذا إلى مسح الذاكرة المؤقتة وإجراء طلب جديد إلى الخادم، مما يضمن عرض أحدث البيانات.
يمكنك أيضًا الانسحاب من الجلب المسبق عن طريق تعيين خاصية prefetch
لمكون <Link>
إلى false
. ومع ذلك، سيظل هذا يقوم بتخزين أجزاء المسار مؤقتًا لمدة 30 ثانية للسماح بالتنقل الفوري بين الأجزاء المتداخلة، مثل أشرطة التبويب، أو التنقل للخلف والأمام. سيتم تخزين المسارات التي تمت زيارتها مؤقتًا.
تفاعلات الذاكرة المؤقتة
عند تكوين آليات التخزين المؤقت المختلفة، من المهم فهم كيفية تفاعلها مع بعضها البعض:
ذاكرة البيانات وذاكرة المسار الكاملة
- إعادة التحقق أو الانسحاب من ذاكرة البيانات سوف يبطل ذاكرة المسار الكاملة، حيث يعتمد ناتج العرض على البيانات.
- إبطال أو الانسحاب من ذاكرة المسار الكاملة لا يؤثر على ذاكرة البيانات. يمكنك عرض مسار ديناميكي يحتوي على بيانات مخزنة وغير مخزنة. هذا مفيد عندما تستخدم معظم صفحتك بيانات مخزنة، ولكن لديك بعض المكونات التي تعتمد على البيانات التي تحتاج إلى جلبها في وقت الطلب. يمكنك العرض ديناميكيًا دون القلق بشأن تأثير الأداء لإعادة جلب جميع البيانات.
ذاكرة البيانات وذاكرة التوجيه على العميل
- إعادة التحقق من ذاكرة البيانات في معالج المسار (Route Handler) لن يبطل ذاكرة التوجيه على الفور لأن معالج المسار غير مرتب بمسار محدد. وهذا يعني أن ذاكرة التوجيه ستستمر في تقديم الحمولة السابقة حتى تحديث قوي، أو انتهاء فترة الإبطال التلقائي.
- لإبطال ذاكرة البيانات وذاكرة التوجيه على الفور، يمكنك استخدام
revalidatePath
أوrevalidateTag
في إجراء خادم (Server Action).
واجهات برمجة التطبيقات (APIs)
يوضح الجدول التالي نظرة عامة على كيفية تأثير واجهات برمجة التطبيقات المختلفة لـ Next.js على التخزين المؤقت:
الواجهة البرمجية | ذاكرة التوجيه | ذاكرة المسار الكاملة | ذاكرة البيانات | ذاكرة React |
---|---|---|---|---|
<Link prefetch> | تخزين مؤقت | |||
router.prefetch | تخزين مؤقت | |||
router.refresh | إعادة التحقق | |||
fetch | تخزين مؤقت | تخزين مؤقت | ||
fetch options.cache | تخزين مؤقت أو انسحاب | |||
fetch options.next.revalidate | إعادة التحقق | إعادة التحقق | ||
fetch options.next.tags | تخزين مؤقت | تخزين مؤقت | ||
revalidateTag | إعادة التحقق (إجراء خادم) | إعادة التحقق | إعادة التحقق | |
revalidatePath | إعادة التحقق (إجراء خادم) | إعادة التحقق | إعادة التحقق | |
const revalidate | إعادة التحقق أو انسحاب | إعادة التحقق أو انسحاب | ||
const dynamic | تخزين مؤقت أو انسحاب | تخزين مؤقت أو انسحاب | ||
cookies | إعادة التحقق (إجراء خادم) | انسحاب | ||
headers , searchParams | انسحاب | |||
generateStaticParams | تخزين مؤقت | |||
React.cache | تخزين مؤقت | |||
unstable_cache |
<Link>
افتراضيًا، يقوم مكون <Link>
تلقائيًا بجلب المسارات مسبقًا من ذاكرة المسار الكاملة وإضافة حمولة مكونات خادم React إلى ذاكرة التوجيه.
لتعطيل الجلب المسبق، يمكنك تعيين خاصية prefetch
إلى false
. ولكن هذا لن يتخطى التخزين المؤقت بشكل دائم، سيتم تخزين جزء المسار على جانب العميل عندما يزور المستخدم المسار.
تعرف على المزيد حول مكون <Link>
.
router.prefetch
يمكن استخدام خيار prefetch
في خطاف useRouter
لجلب مسار مسبقًا يدويًا. هذا يضيف حمولة مكونات خادم React إلى ذاكرة التوجيه.
راجع مرجع خطاف useRouter
.
router.refresh
يمكن استخدام خيار refresh
في خطاف useRouter
لتحديث مسار يدويًا. هذا يمسح ذاكرة التوجيه بالكامل، ويجعل طلبًا جديدًا إلى الخادم للمسار الحالي. لا يؤثر refresh
على ذاكرة البيانات أو ذاكرة المسار الكاملة.
سيتم مصالحة النتيجة المعروضة على العميل مع الحفاظ على حالة React وحالة المتصفح.
راجع مرجع خطاف useRouter
.
fetch
يتم تخزين البيانات المرتجعة من fetch
تلقائيًا في ذاكرة البيانات.
// مخزن مؤقتًا افتراضيًا. `force-cache` هو الخيار الافتراضي ويمكن حذفه.
fetch(`https://...`, { cache: 'force-cache' })
راجع مرجع واجهة fetch
لمزيد من الخيارات.
fetch options.cache
يمكنك الانسحاب من تخزين طلبات fetch
الفردية للبيانات عن طريق تعيين خيار cache
إلى no-store
:
// الانسحاب من التخزين المؤقت
fetch(`https://...`, { cache: 'no-store' })
نظرًا لأن ناتج العرض يعتمد على البيانات، فإن استخدام cache: 'no-store'
سيتخطى أيضًا ذاكرة المسار الكاملة للمسار الذي يتم فيه استخدام طلب fetch
. أي أنه سيتم عرض المسار ديناميكيًا في كل طلب، ولكن لا يزال بإمكانك الحصول على طلبات بيانات مخزنة أخرى في نفس المسار.
راجع مرجع واجهة fetch
لمزيد من الخيارات.
fetch options.next.revalidate
يمكنك استخدام خيار next.revalidate
في fetch
لتعيين فترة إعادة التحقق (بالثواني) لطلب fetch
فردي. سيعيد هذا التحقق من ذاكرة البيانات، مما سيعيد بدوره التحقق من ذاكرة المسار الكاملة. سيتم جلب بيانات جديدة، وسيتم إعادة عرض المكونات على الخادم.
// إعادة التحقق على الأكثر بعد ساعة واحدة
fetch(`https://...`, { next: { revalidate: 3600 } })
راجع مرجع واجهة fetch
لمزيد من الخيارات.
fetch options.next.tags
و revalidateTag
يقدم Next.js نظامًا لوضع علامات على ذاكرة التخزين المؤقت للتحكم الدقيق في تخزين البيانات وإعادة التحقق منها.
- عند استخدام
fetch
أوunstable_cache
، يمكنك وضع علامة واحدة أو أكثر على مدخلات ذاكرة التخزين المؤقت. - ثم يمكنك استدعاء
revalidateTag
لمسح مدخلات ذاكرة التخزين المؤقت المرتبطة بتلك العلامة.
على سبيل المثال، يمكنك تعيين علامة عند جلب البيانات:
// تخزين البيانات مع علامة
fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } })
ثم استدعاء revalidateTag
مع علامة لمسح مدخل ذاكرة التخزين المؤقت:
// إعادة التحقق من المدخلات ذات العلامة المحددة
revalidateTag('a')
هناك مكانان يمكنك استخدام revalidateTag
فيهما، حسب ما تحاول تحقيقه:
- معالجات المسارات (Route Handlers) - لإعادة التحقق من البيانات استجابةً لحدث طرف ثالث (مثل webhook). لن يؤدي هذا إلى إبطال ذاكرة تخزين المسار (Router Cache) فورًا لأن معالج المسار غير مرتبط بمسار محدد.
- الإجراءات الخادمية (Server Actions) - لإعادة التحقق من البيانات بعد إجراء المستخدم (مثل إرسال نموذج). سيؤدي هذا إلى إبطال ذاكرة تخزين المسار للمسار المرتبط.
revalidatePath
يسمح لك revalidatePath
بإعادة التحقق من البيانات يدويًا و إعادة عرض مقاطع المسار أسفل مسار محدد في عملية واحدة. يؤدي استدعاء دالة revalidatePath
إلى إعادة التحقق من ذاكرة تخزين البيانات (Data Cache)، مما يؤدي بدوره إلى إبطال ذاكرة تخزين المسار الكاملة (Full Route Cache).
revalidatePath('/')
هناك مكانان يمكنك استخدام revalidatePath
فيهما، حسب ما تحاول تحقيقه:
- معالجات المسارات (Route Handlers) - لإعادة التحقق من البيانات استجابةً لحدث طرف ثالث (مثل webhook).
- الإجراءات الخادمية (Server Actions) - لإعادة التحقق من البيانات بعد تفاعل المستخدم (مثل إرسال نموذج، النقر على زر).
راجع مرجع واجهة برمجة التطبيقات لـ revalidatePath
لمزيد من المعلومات.
مقارنة بين
revalidatePath
وrouter.refresh
:يؤدي استدعاء
router.refresh
إلى مسح ذاكرة تخزين المسار (Router Cache)، وإعادة عرض مقاطع المسار على الخادم دون إبطال ذاكرة تخزين البيانات (Data Cache) أو ذاكرة تخزين المسار الكاملة (Full Route Cache).الفرق هو أن
revalidatePath
يمسح ذاكرة تخزين البيانات وذاكرة تخزين المسار الكاملة، بينماrouter.refresh()
لا يغير ذاكرة تخزين البيانات وذاكرة تخزين المسار الكاملة، لأنه واجهة برمجة تطبيقات من جانب العميل.
الدوال الديناميكية
تعتمد الدوال الديناميكية مثل cookies
و headers
، وخاصية searchParams
في الصفحات على معلومات الطلب الواردة أثناء التشغيل. يؤدي استخدامها إلى استبعاد المسار من ذاكرة تخزين المسار الكاملة، بمعنى آخر، سيتم عرض المسار ديناميكيًا.
cookies
يؤدي استخدام cookies.set
أو cookies.delete
في إجراء خادمي (Server Action) إلى إبطال ذاكرة تخزين المسار (Router Cache) لمنع المسارات التي تستخدم ملفات تعريف الارتباط من أن تصبح قديمة (على سبيل المثال، لتعكس تغييرات المصادقة).
راجع مرجع واجهة برمجة التطبيقات لـ cookies
.
خيارات تكوين المقاطع
يمكن استخدام خيارات تكوين مقطع المسار (Route Segment Config) لتجاوز الإعدادات الافتراضية لمقطع المسار أو عندما لا يمكنك استخدام واجهة برمجة التطبيقات fetch
(على سبيل المثال، عميل قاعدة بيانات أو مكتبات طرف ثالث).
ستؤدي خيارات تكوين مقطع المسار التالية إلى استبعاد المسار من ذاكرة تخزين البيانات وذاكرة تخزين المسار الكاملة:
const dynamic = 'force-dynamic'
const revalidate = 0
راجع توثيق تكوين مقاطع المسار (Route Segment Config) لمزيد من الخيارات.
generateStaticParams
بالنسبة للمقاطع الديناميكية (على سبيل المثال، app/blog/[slug]/page.js
)، يتم تخزين المسارات المقدمة من generateStaticParams
في ذاكرة تخزين المسار الكاملة (Full Route Cache) وقت البناء. عند وقت الطلب، سيخزن Next.js أيضًا المسارات التي لم تكن معروفة وقت البناء عند زيارتها لأول مرة.
يمكنك تعطيل التخزين المؤقت عند وقت الطلب باستخدام خيار export const dynamicParams = false
في مقطع المسار. عند استخدام خيار التكوين هذا، سيتم تقديم المسارات المقدمة من generateStaticParams
فقط، وستؤدي المسارات الأخرى إلى ظهور خطأ 404 أو تطابق (في حالة المقاطع الشاملة (catch-all routes)).
راجع مرجع واجهة برمجة التطبيقات لـ generateStaticParams
.
دالة React cache
تسمح لك دالة React cache
بحفظ قيمة الإرجاع للدالة، مما يتيح لك استدعاء نفس الدالة عدة مرات مع تنفيذها مرة واحدة فقط.
نظرًا لأن طلبات fetch
يتم حفظها تلقائيًا، فلا تحتاج إلى تغليفها في React cache
. ومع ذلك، يمكنك استخدام cache
لحفظ طلبات البيانات يدويًا للحالات التي لا تكون فيها واجهة برمجة التطبيقات fetch
مناسبة. على سبيل المثال، بعض عملاء قواعد البيانات، أو عملاء أنظمة إدارة المحتوى (CMS)، أو عملاء GraphQL.
import { cache } from 'react'
import db from '@/lib/db'
export const getItem = cache(async (id: string) => {
const item = await db.item.findUnique({ id })
return item
})
import { cache } from 'react'
import db from '@/lib/db'
export const getItem = cache(async (id) => {
const item = await db.item.findUnique({ id })
return item
})