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

يتغير سلوك التخزين المؤقت اعتمادًا على ما إذا كان المسار يتم تصييره بشكل ثابت أو ديناميكي، وما إذا كانت البيانات مخزنة مؤقتًا أو غير مخزنة، وما إذا كان الطلب جزءًا من زيارة أولية أو تنقل لاحق. اعتمادًا على حالة الاستخدام الخاصة بك، يمكنك تكوين سلوك التخزين المؤقت للمسارات الفردية وطلبات البيانات.
تخزين الطلبات مؤقتًا (Request Memoization)
يمتد Next.js لواجهة برمجة التطبيقات 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
إلى كيفية تفاعل طلب الخادم مع ذاكرة تخزين بيانات الخادم.
يمكنك استخدام خيارات cache
وnext.revalidate
لـ fetch
لتكوين سلوك التخزين المؤقت.
كيف تعمل ذاكرة تخزين البيانات

- في المرة الأولى التي يتم فيها استدعاء طلب
fetch
مع خيار'force-cache'
أثناء التصيير، يتحقق Next.js من ذاكرة تخزين البيانات بحثًا عن استجابة مخزنة. - إذا تم العثور على استجابة مخزنة، يتم إرجاعها على الفور وتخزينها مؤقتًا.
- إذا لم يتم العثور على استجابة مخزنة، يتم إجراء الطلب إلى مصدر البيانات، وتخزين النتيجة في ذاكرة تخزين البيانات، وتخزينها مؤقتًا.
- بالنسبة للبيانات غير المخزنة (مثل عدم تعريف خيار
cache
أو استخدام{ cache: 'no-store' }
)، يتم دائمًا جلب النتيجة من مصدر البيانات، وتخزينها مؤقتًا. - سواء كانت البيانات مخزنة أو غير مخزنة، يتم دائمًا تخزين الطلبات مؤقتًا لتجنب إنشاء طلبات مكررة لنفس البيانات أثناء تمرير تصيير React.
الاختلافات بين ذاكرة تخزين البيانات وتخزين الطلبات مؤقتًا
بينما تساعد آليتا التخزين المؤقت في تحسين الأداء من خلال إعادة استخدام البيانات المخزنة مؤقتًا، فإن ذاكرة تخزين البيانات تستمر عبر الطلبات الواردة والنشرات، بينما يستمر تخزين الطلبات مؤقتًا فقط طوال عمر الطلب.
المدة
تستمر ذاكرة تخزين البيانات عبر الطلبات الواردة والنشرات ما لم تقم بإعادة التحقق أو عدم التخزين المؤقت.
إعادة التحقق
يمكن إعادة التحقق من البيانات المخزنة مؤقتًا بطريقتين، باستخدام:
- إعادة التحقق بناءً على الوقت: إعادة التحقق من البيانات بعد مرور فترة زمنية معينة وإجراء طلب جديد. هذا مفيد للبيانات التي تتغير بشكل غير متكرر ولا تكون الحداثة حرجة.
- إعادة التحقق عند الطلب: إعادة التحقق من البيانات بناءً على حدث (مثل إرسال نموذج). يمكن أن تستخدم إعادة التحقق عند الطلب نهجًا يعتمد على العلامات أو المسار لإعادة التحقق من مجموعات البيانات دفعة واحدة. هذا مفيد عندما تريد التأكد من عرض أحدث البيانات في أسرع وقت ممكن (مثل عند تحديث المحتوى من نظام إدارة المحتوى الخاص بك).
إعادة التحقق بناءً على الوقت
لإعادة التحقق من البيانات على فترات زمنية، يمكنك استخدام خيار 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
مرة أخرى، وسيتم جلب البيانات من مصدر البيانات الخارجي وتخزينها في ذاكرة تخزين البيانات.
عدم التخزين المؤقت
إذا كنت لا تريد تخزين الاستجابة من fetch
مؤقتًا، يمكنك القيام بما يلي:
let data = await fetch('https://api.vercel.app/blog', { cache: 'no-store' })
ذاكرة تخزين المسار الكامل (Full Route Cache)
المصطلحات ذات الصلة:
قد ترى المصطلحات التحسين الثابت التلقائي، أو إنشاء موقع ثابت، أو التصيير الثابت تُستخدم بالتبادل للإشارة إلى عملية تصيير وتخزين مسارات تطبيقك في وقت البناء.
يقوم Next.js تلقائيًا بتصيير وتخزين المسارات مؤقتًا في وقت البناء. هذا تحسين يسمح لك بتقديم المسار المخزن مؤقتًا بدلاً من التصيير على الخادم لكل طلب، مما يؤدي إلى تحميل أسرع للصفحات.
لفهم كيفية عمل ذاكرة تخزين المسار الكامل، من المفيد النظر إلى كيفية تعامل React مع التصيير، وكيف يقوم Next.js بتخزين النتيجة:
1. تصيير React على الخادم
على الخادم، يستخدم Next.js واجهات برمجة تطبيقات React لتنظيم التصيير. يتم تقسيم عمل التصيير إلى أجزاء: حسب مقاطع المسار الفردية وحدود Suspense.
يتم تصيير كل جزء في خطوتين:
- يقوم React بتصيير مكونات الخادم إلى تنسيق بيانات خاص مُحسَّن للبث، يسمى حمولة مكون خادم React.
- يستخدم Next.js حمولة مكون خادم React وتعليمات JavaScript لمكون العميل لتصيير HTML على الخادم.
هذا يعني أننا لسنا مضطرين إلى انتظار اكتمال كل شيء قبل تخزين العمل أو إرسال استجابة. بدلاً من ذلك، يمكننا بث استجابة أثناء اكتمال العمل.
ما هي حمولة مكون خادم React؟
حمولة مكون خادم React هي تمثيل ثنائي مضغوط لشجرة مكونات خادم React المصيرة. يتم استخدامها بواسطة React على العميل لتحديث DOM للمتصفح. تحتوي حمولة مكون خادم React على:
- نتيجة تصيير مكونات الخادم
- عناصر نائبة لمكان تصيير مكونات العميل ومراجع لملفات JavaScript الخاصة بها
- أي خصائص تم تمريرها من مكون خادم إلى مكون عميل
لمعرفة المزيد، راجع وثائق مكونات الخادم.
2. تخزين Next.js على الخادم (ذاكرة تخزين المسار الكامل)

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

تعلم المزيد حول التقديم الثابت والديناميكي.
المدة
افتراضيًا، ذاكرة التخزين المؤقت الكاملة للمسار دائمة. هذا يعني أن ناتج التقديم يتم تخزينه مؤقتًا عبر طلبات المستخدم.
الإبطال
هناك طريقتان يمكنك من خلالهما إبطال ذاكرة التخزين المؤقت الكاملة للمسار:
- إعادة التحقق من البيانات: إعادة التحقق من ذاكرة التخزين المؤقت للبيانات سوف يؤدي بدوره إلى إبطال ذاكرة التخزين المؤقت للموجه عن طريق إعادة تقديم المكونات على الخادم وتخزين ناتج التقديم الجديد مؤقتًا.
- إعادة النشر: على عكس ذاكرة التخزين المؤقت للبيانات، التي تظل عبر عمليات النشر، يتم مسح ذاكرة التخزين المؤقت الكاملة للمسار عند عمليات النشر الجديدة.
الانسحاب
يمكنك الانسحاب من ذاكرة التخزين المؤقت الكاملة للمسار، أو بعبارة أخرى، تقديم المكونات ديناميكيًا لكل طلب وارد، عن طريق:
- استخدام واجهة برمجة التطبيقات الديناميكية: هذا سوف يخرج المسار من ذاكرة التخزين المؤقت الكاملة للمسار ويقدمه ديناميكيًا عند وقت الطلب. لا يزال يمكن استخدام ذاكرة التخزين المؤقت للبيانات.
- استخدام خيارات تكوين قطعة المسار
dynamic = 'force-dynamic'
أوrevalidate = 0
: هذا سيتخطى ذاكرة التخزين المؤقت الكاملة للمسار وذاكرة التخزين المؤقت للبيانات. مما يعني أن المكونات سيتم تقديمها وجلب البيانات في كل طلب وارد إلى الخادم. ستظل ذاكرة التخزين المؤقت للموجه سارية لأنها ذاكرة تخزين مؤقت على جانب العميل. - الانسحاب من ذاكرة التخزين المؤقت للبيانات: إذا كان المسار يحتوي على طلب
fetch
غير مخزن مؤقتًا، فإن هذا سوف يخرج المسار من ذاكرة التخزين المؤقت الكاملة للمسار. سيتم جلب البيانات لطلبfetch
المحدد لكل طلب وارد. طلباتfetch
الأخرى التي لا تنسحب من التخزين المؤقت ستظل مخزنة في ذاكرة التخزين المؤقت للبيانات. هذا يسمح بمزيج من البيانات المخزنة وغير المخزنة.
ذاكرة التخزين المؤقت للموجه على جانب العميل
يحتوي Next.js على ذاكرة تخزين مؤقت للموجه على جانب العميل في الذاكرة تقوم بتخزين حمولة RSC لقطع المسار، مقسمة حسب التخطيطات وحالات التحميل والصفحات.
عندما يتنقل المستخدم بين المسارات، يقوم Next.js بتخزين قطع المسار التي تمت زيارتها مسبقًا وجلبها مسبقًا للمسارات التي من المحتمل أن ينتقل إليها المستخدم. يؤدي هذا إلى تنقل فوري للخلف/الأمام، دون إعادة تحميل كاملة للصفحة بين التنقلات، والحفاظ على حالة React وحالة المتصفح.
مع ذاكرة التخزين المؤقت للموجه:
- التخطيطات يتم تخزينها وإعادة استخدامها أثناء التنقل (التقديم الجزئي).
- حالات التحميل يتم تخزينها وإعادة استخدامها أثناء التنقل لـتنقل فوري.
- الصفحات لا يتم تخزينها افتراضيًا، ولكن يتم إعادة استخدامها أثناء التنقل للخلف والأمام في المتصفح. يمكنك تمكين التخزين المؤقت لقطع الصفحات باستخدام خيار التكوين التجريبي
staleTimes
.
من الجيد معرفة: هذه الذاكرة المؤقتة تنطبق تحديدًا على Next.js ومكونات الخادم، وتختلف عن bfcache للمتصفح، على الرغم من أن لها نتيجة مماثلة.
المدة
يتم تخزين الذاكرة المؤقتة في الذاكرة المؤقتة للمتصفح. هناك عاملان يحددان مدة بقاء ذاكرة التخزين المؤقت للموجه:
- الجلسة: تظل الذاكرة المؤقتة عبر التنقل. ومع ذلك، يتم مسحها عند تحديث الصفحة.
- فترة الإبطال التلقائي: يتم إبطال ذاكرة التخزين المؤقت للتخطيطات وحالات التحميل تلقائيًا بعد وقت محدد. تعتمد المدة على كيفية جلب المورد مسبقًا، وما إذا كان المورد قد تم توليده بشكل ثابت:
- الجلب المسبق الافتراضي (
prefetch={null}
أو غير محدد): لا يتم تخزينه للصفحات الديناميكية، 5 دقائق للصفحات الثابتة. - الجلب المسبق الكامل (
prefetch={true}
أوrouter.prefetch
): 5 دقائق لكل من الصفحات الثابتة والديناميكية.
- الجلب المسبق الافتراضي (
بينما يؤدي تحديث الصفحة إلى مسح جميع القطع المخزنة مؤقتًا، فإن فترة الإبطال التلقائي تؤثر فقط على القطعة الفردية من وقت جلبها مسبقًا.
من الجيد معرفة: يمكن استخدام خيار التكوين التجريبي
staleTimes
لضبط أوقات الإبطال التلقائي المذكورة أعلاه.
الإبطال
هناك طريقتان يمكنك من خلالهما إبطال ذاكرة التخزين المؤقت للموجه:
- في إجراء خادم:
- إعادة التحقق من البيانات عند الطلب حسب المسار باستخدام (
revalidatePath
) أو حسب علامة التخزين المؤقت باستخدام (revalidateTag
) - استخدام
cookies.set
أوcookies.delete
يبطل ذاكرة التخزين المؤقت للموجه لمنع المسارات التي تستخدم ملفات تعريف الارتباط من أن تصبح قديمة (مثل المصادقة).
- إعادة التحقق من البيانات عند الطلب حسب المسار باستخدام (
- استدعاء
router.refresh
سوف يبطل ذاكرة التخزين المؤقت للموجه ويجعل طلبًا جديدًا إلى الخادم للمسار الحالي.
الانسحاب
اعتبارًا من Next.js 15، يتم الانسحاب من قطع الصفحات افتراضيًا.
من الجيد معرفة: يمكنك أيضًا الانسحاب من الجلب المسبق عن طريق تعيين خاصية
prefetch
لمكون<Link>
إلىfalse
.
تفاعلات التخزين المؤقت
عند تكوين آليات التخزين المؤقت المختلفة، من المهم فهم كيفية تفاعلها مع بعضها البعض:
ذاكرة التخزين المؤقت للبيانات وذاكرة التخزين المؤقت الكاملة للمسار
- إعادة التحقق أو الانسحاب من ذاكرة التخزين المؤقت للبيانات سوف يبطل ذاكرة التخزين المؤقت الكاملة للمسار، لأن ناتج التقديم يعتمد على البيانات.
- إبطال أو الانسحاب من ذاكرة التخزين المؤقت الكاملة للمسار لا يؤثر على ذاكرة التخزين المؤقت للبيانات. يمكنك تقديم مسار ديناميكي يحتوي على كل من البيانات المخزنة وغير المخزنة. هذا مفيد عندما تستخدم معظم صفحتك بيانات مخزنة، ولكن لديك بعض المكونات التي تعتمد على بيانات تحتاج إلى جلبها عند وقت الطلب. يمكنك التقديم ديناميكيًا دون القلق بشأن تأثير الأداء لإعادة جلب جميع البيانات.
ذاكرة التخزين المؤقت للبيانات وذاكرة التخزين المؤقت للموجه على جانب العميل
- لإبطال ذاكرة التخزين المؤقت للبيانات وذاكرة الموجه على الفور، يمكنك استخدام
revalidatePath
أوrevalidateTag
في إجراء خادم. - إعادة التحقق من ذاكرة التخزين المؤقت للبيانات في معالج المسار لن يبطل ذاكرة التخزين المؤقت للموجه على الفور لأن معالج المسار غير مرتب بمسار محدد. هذا يعني أن ذاكرة التخزين المؤقت للموجه ستستمر في تقديم الحمولة السابقة حتى تحديث قوي، أو انتهاء فترة الإبطال التلقائي.
واجهات برمجة التطبيقات
يوضح الجدول التالي نظرة عامة حول كيفية تأثير واجهات برمجة التطبيقات المختلفة لـ 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
لا يتم تخزينها تلقائيًا في ذاكرة التخزين المؤقت للبيانات.
سلوك التخزين المؤقت الافتراضي لـ fetch
(على سبيل المثال، عندما لا يتم تحديد خيار cache
) يساوي تعيين خيار cache
إلى no-store
:
let data = await fetch('https://api.vercel.app/blog', { cache: 'no-store' })
راجع مرجع واجهة برمجة التطبيقات لـ fetch
لمزيد من الخيارات.
fetch options.cache
يمكنك اختيار تخزين fetch
الفردي مؤقتًا عن طريق تعيين خيار cache
إلى force-cache
:
// اختيار التخزين المؤقت
fetch(`https://...`, { cache: 'force-cache' })
راجع مرجع واجهة برمجة التطبيقات لـ 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
فيهما، اعتمادًا على ما تحاول تحقيقه:
- معالجات المسار - لإعادة التحقق من البيانات استجابة لحدث طرف ثالث (مثل webhook). هذا لن يبطل ذاكرة التخزين المؤقت للموجه على الفور لأن معالج المسار غير مرتب بمسار محدد.
- إجراءات الخادم - لإعادة التحقق من البيانات بعد إجراء مستخدم (مثل تقديم نموذج). هذا سيبطل ذاكرة التخزين المؤقت للموجه للمسار المرتبط.
revalidatePath
يسمح لك revalidatePath
بإعادة التحقق من البيانات يدويًا و إعادة تقديم قطع المسار أسفل مسار محدد في عملية واحدة. يؤدي استدعاء طريقة revalidatePath
إلى إعادة التحقق من ذاكرة التخزين المؤقت للبيانات، والتي بدورها تبطل ذاكرة التخزين المؤقت الكاملة للمسار.
revalidatePath('/')
هناك مكانان يمكنك استخدام revalidatePath
فيهما، اعتمادًا على ما تحاول تحقيقه:
- معالجات المسار - لإعادة التحقق من البيانات استجابة لحدث طرف ثالث (مثل webhook).
- إجراءات الخادم - لإعادة التحقق من البيانات بعد تفاعل المستخدم (مثل تقديم نموذج، النقر على زر).
راجع مرجع واجهة برمجة التطبيقات لـ revalidatePath
لمزيد من المعلومات.
revalidatePath
مقابلrouter.refresh
:يؤدي استدعاء
router.refresh
إلى مسح ذاكرة التخزين المؤقت للموجه، وإعادة تقديم قطع المسار على الخادم دون إبطال ذاكرة التخزين المؤقت للبيانات أو ذاكرة المسار الكاملة.الفرق هو أن
revalidatePath
يمسح ذاكرة التخزين المؤقت للبيانات وذاكرة المسار الكاملة، بينماrouter.refresh()
لا يغير ذاكرة التخزين المؤقت للبيانات وذاكرة المسار الكاملة، لأنه واجهة برمجة تطبيقات على جانب العميل.
واجهات برمجة التطبيقات الديناميكية
تعتمد واجهات برمجة التطبيقات الديناميكية مثل cookies
و headers
، وخاصية searchParams
في الصفحات على معلومات الطلب الواردة أثناء التشغيل. استخدامها سوف يخرج المسار من ذاكرة التخزين المؤقت الكاملة للمسار، بعبارة أخرى، سيتم تقديم المسار ديناميكيًا.
cookies
استخدام cookies.set
أو cookies.delete
في إجراء خادم يبطل ذاكرة التخزين المؤقت للموجه لمنع المسارات التي تستخدم ملفات تعريف الارتباط من أن تصبح قديمة (مثل عكس تغييرات المصادقة).
راجع مرجع واجهة برمجة التطبيقات لـ cookies
.
خيارات تكوين القطاع (Segment Config Options)
يمكن استخدام خيارات تكوين قطاع المسار (Route Segment Config) لتجاوز الإعدادات الافتراضية لقطاع المسار أو عندما لا تتمكن من استخدام واجهة برمجة التطبيقات fetch
(مثل عميل قاعدة البيانات أو مكتبات الطرف الثالث).
ستؤدي خيارات تكوين قطاع المسار التالية إلى إلغاء اختيار ذاكرة التخزين المؤقت الكاملة للمسار (Full Route Cache):
const dynamic = 'force-dynamic'
سيؤدي خيار التكوين هذا إلى إلغاء اختيار جميع عمليات الجلب من ذاكرة التخزين المؤقت للبيانات (Data Cache) (أي no-store
):
const fetchCache = 'default-no-store'
راجع fetchCache
لمشاهدة خيارات أكثر تقدمًا.
راجع وثائق تكوين قطاع المسار لمزيد من الخيارات.
generateStaticParams
بالنسبة للقطاعات الديناميكية (dynamic segments) (مثل app/blog/[slug]/page.js
)، يتم تخزين المسارات المقدمة من خلال generateStaticParams
في ذاكرة التخزين المؤقت الكاملة للمسار (Full Route Cache) وقت البناء. عند الطلب، سيخزن Next.js أيضًا المسارات التي لم تكن معروفة وقت البناء عند زيارتها لأول مرة.
لتصيير جميع المسارات بشكل ثابت وقت البناء، قم بتوفير القائمة الكاملة للمسارات لـ generateStaticParams
:
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
لتصيير مجموعة فرعية من المسارات بشكل ثابت وقت البناء، والباقي عند زيارتها لأول مرة أثناء التشغيل، قم بإرجاع قائمة جزئية من المسارات:
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
// تصيير أول 10 منشورات وقت البناء
return posts.slice(0, 10).map((post) => ({
slug: post.slug,
}))
}
لتصيير جميع المسارات بشكل ثابت عند زيارتها لأول مرة، قم بإرجاع مصفوفة فارغة (لن يتم تصيير أي مسارات وقت البناء) أو استخدم export const dynamic = 'force-static'
:
export async function generateStaticParams() {
return []
}
معلومة مفيدة: يجب عليك إرجاع مصفوفة من
generateStaticParams
، حتى لو كانت فارغة. وإلا، سيتم تصيير المسار بشكل ديناميكي.
export const dynamic = 'force-static'
لتعطيل التخزين المؤقت وقت الطلب، أضف خيار export const dynamicParams = false
في قطاع المسار. عند استخدام خيار التكوين هذا، سيتم تقديم المسارات المقدمة من generateStaticParams
فقط، وسيؤدي المسارات الأخرى إلى ظهور خطأ 404 أو تطابق (في حالة المسارات الشاملة).
دالة cache
في React
تتيح لك دالة cache
في React حفظ القيمة المرجعة للدالة، مما يسمح لك باستدعاء نفس الدالة عدة مرات مع تنفيذها مرة واحدة فقط.
نظرًا لأن طلبات fetch
يتم حفظها تلقائيًا، لا تحتاج إلى تغليفها في cache
في React. ومع ذلك، يمكنك استخدام 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
})