Next.js
مسیریاب app
برنامه تان را بسیازید
کش کردن

کش کردن در Next.js

Next.js با کش کردن کار رندرینگ و درخواست های داده، عملکرد برنامه شما را بهبود می بخشد و هزینه ها را کاهش می دهد. این صفحه نگاهی عمیق به مکانیزم های کش Next.js، API هایی که می توانید برای پیکربندی آنها استفاده کنید و نحوه تعامل آنها با یکدیگر ارائه می دهد.

خوب است بدانید: این صفحه به شما کمک می کند تا نحوه عملکرد Next.js در زیر کاپوت را درک کنید، اما برای بهره وری با Next.js دانش ضروری نیست. بیشتر محاسبات کش Next.js با استفاده از API شما تعیین می شود و برای بهترین عملکرد با پیکربندی صفر یا حداقل پیش فرض دارد.

بررسی اجمالی

در اینجا یک نمای کلی از مکانیزم های مختلف کش و هدف آنها آورده شده است:

مکانیزمچیجایی کهمقصودمدت زمان
Memoization درخواستمقادیر بازگشتی توابعسروراستفاده مجدد از داده ها در درخت کامپوننت Reactچرخه زندگی برای هر درخواست
کش دادهدادهسرورذخیره داده‌ها در طول درخواست‌های کاربر و روند استقرارپایدار (قابل اعتبارسنجی مجدد)
کش کامل مسیرHTML and RSC payloadسرورکاهش هزینه‌ی رندرینگ و بهبود عملکردپایدار (قابل اعتبارسنجی مجدد)
کش مسیریابRSC Payloadکلاینتکاهش درخواست‌های سرور در حین پیمایشنشست کاربر یا بر اساس زمان

به طور پیش فرض، Next.js تا حد امکان کش می کند تا عملکرد را بهبود بخشد و هزینه را کاهش دهد. این بدان معناست که مسیرها به صورت استاتیک رندر می شوند و درخواست های داده کش می شوند مگر اینکه شما انصراف دهید. نمودار زیر رفتار پیش فرض کش را نشان می دهد: زمانی که یک مسیر در زمان ساخت به صورت استاتیک رندر می شود و زمانی که اولین بار از یک مسیر استاتیک بازدید می شود.


نموداری از رفتار حافظه پنهان پیش‌فرض در Next.js برای چهار مکانیزم، با HIT، MISS و SET در زمان ساخت و زمانی که یک مسیر برای اولین بار بازدید می‌شود.نموداری از رفتار حافظه پنهان پیش‌فرض در Next.js برای چهار مکانیزم، با HIT، MISS و SET در زمان ساخت و زمانی که یک مسیر برای اولین بار بازدید می‌شود.

رفتار کش بسته به اینکه مسیر به صورت استاتیک یا پویا رندر شده باشد، داده کش شده یا نشده باشد و اینکه آیا یک درخواست بخشی از بازدید اولیه یا پیمایش بعدی است، تغییر می کند. بسته به مورد استفاده خود، می توانید رفتار کش را برای مسیرهای جداگانه و درخواست های داده پیکربندی کنید.

Memoization درخواست

React fetch API را برای به طور خودکار memoize درخواست هایی که URL و گزینه های یکسانی دارند، گسترش می دهد. این بدان معناست که شما می توانید یک تابع fetch را برای داده های مشابه در چندین مکان در یک درخت کامپوننت React فراخوانی کنید در حالی که فقط یک بار آن را اجرا کنید.


درخواست های دریافت کپی شدهدرخواست های دریافت کپی شده

به عنوان مثال، اگر نیاز به استفاده از داده های مشابه در یک مسیر (مثلاً در طرح بندی، صفحه و چندین کامپوننت) دارید، لازم نیست داده ها را در بالای درخت دریافت کنید و prop ها را بین کامپوننت ها ارسال کنید. در عوض، می توانید داده ها را در کامپوننت هایی که به آنها نیاز دارند بدون نگرانی در مورد پیامدهای عملکردی ایجاد چندین درخواست در سراسر شبکه برای داده های مشابه، دریافت کنید.

app/example.tsx
async function getItem() {
	// The `fetch` function is automatically memoized and the result
	// is cached
	const res = await fetch('https://.../item/1')
	return res.json()
}
 
// This function is called twice, but only executed the first time
const item = await getItem() // cache MISS
 
// The second call could be anywhere in your route
const item = await getItem() // cache HIT

Memoization درخواست چگونه کار می کند


نموداری که نشان دهنده نحوه‌ی عملکرد Memoization در حین رندرینگ React است.نموداری که نشان دهنده نحوه‌ی عملکرد Memoization در حین رندرینگ React است.
  • در حین رندر کردن یک مسیر، اولین باری که یک درخواست خاص فراخوانده می شود، نتیجه آن در حافظه موجود نبوده و به عنوان یک "MISS" در حافظه پنهان شناخته می‌شود.
  • بنابراین، تابع اجرا خواهد شد و داده ها از منبع خارجی دریافت می شود و نتیجه در حافظه ذخیره می شود.
  • تماس های بعدی تابع درخواست در همان مرحله رندر، یک کش (cache HIT) خواهد بود و داده ها بدون اجرای تابع از حافظه برگردانده می شود.
  • پس از رندر شدن مسیر و تکمیل مرحله رندر، حافظه "بازنشانی Reset" می شود و تمام ورودی های Memoization درخواست پاک می شوند.

خوب است بدانید:

  • Memoization درخواست یک ویژگی React است، نه یک ویژگی Next.js. در اینجا گنجانده شده است تا نشان دهد که چگونه با سایر مکانیزم های کش تعامل دارد.
  • Memoization فقط برای متد GET در درخواست های fetch اعمال می شود.
  • Memoization فقط برای درخت کامپوننت React اعمال می شود، این بدان معنی است که:
    • این به درخواست های fetch در generateMetadata، generateStaticParams، طرح بندی ها، صفحات و سایر سرور کامپوننت ها اعمال می شود.
    • این به درخواست های fetch در هندلرهای مسیر Route Handlers اعمال نمی شود زیرا آنها بخشی از درخت کامپوننت React نیستند.
  • برای مواردی که fetch مناسب نیست (به عنوان مثال برخی از سرویس گیرنده های پایگاه داده، سرویس گیرنده های CMS یا سرویس گیرنده های GraphQL)، می توانید از تابع React cache برای memoize توابع استفاده کنید.

مدت زمان

کش تا پایان عمر یک درخواست سرور تا زمانی که درخت کامپوننت React رندر کامل شود، ادامه دارد.

اعتبارسنجی مجدد

از آنجایی که memoization در بین درخواست های سرور به اشتراک گذاشته نمی شود و فقط در حین رندر اعمال می شود، نیازی به اعتبارسنجی مجدد آن نیست.

انصراف دادن

Memoization فقط برای متد GET در درخواست های fetch اعمال می شود، سایر متدها مانند POST و DELETE memoized نمی شوند. این رفتار پیش فرض یک بهینه سازی React است و ما توصیه نمی کنیم که از آن خارج شوید.

برای مدیریت درخواست های جداگانه، می توانید از ویژگی signal (opens in a new tab) از AbortController (opens in a new tab) استفاده کنید. با این حال، این باعث خروج درخواست ها از memoization نمی شود، بلکه درخواست های در حال انجام را لغو می کند.

app/example.js
const { signal } = new AbortController()
fetch(url, { signal })

کش داده Data Cache

Next.js دارای یک کش داده داخلی است که نتیجه جستجوی داده ها را در سراسر درخواست های سرور ورودی و استقرارها نگه می دارد (persists). این امر به این دلیل امکان پذیر است که نکست جی اس API fetch بومی را گسترش می دهد تا به هر درخواست در سرور اجازه دهد تا معنای ماندگاری کش خود را تعیین کند.

خوب است بدانید: در مرورگر، گزینه cache از fetch نشان می دهد که چگونه یک درخواست با کش HTTP مرورگر تعامل خواهد داشت، در Next.js، گزینه cache نشان می دهد که چگونه یک درخواست سمت سرور با کش داده سرور تعامل خواهد داشت.

به طور پیش فرض، درخواست های داده ای که از fetch استفاده می کنند، کش می شوند. می توانید از گزینه های cache و next.revalidate از fetch برای پیکربندی رفتار کش استفاده کنید.

نحوه عملکرد کش داده Data Cache


نموداری که نشان می‌دهد چگونه درخواست‌های با کش و بدون کش با حافظه داده تعامل دارند. درخواست‌های با کش در حافظه داده ذخیره می‌شوند و memoized هستند، در حالی که درخواست‌های بدون کش از منبع داده دریافت می‌شوند، در کش داده ذخیره نمی‌شوند و memoized هستند.نموداری که نشان می‌دهد چگونه درخواست‌های با کش و بدون کش با حافظه داده تعامل دارند. درخواست‌های با کش در حافظه داده ذخیره می‌شوند و memoized هستند، در حالی که درخواست‌های بدون کش از منبع داده دریافت می‌شوند، در کش داده ذخیره نمی‌شوند و memoized هستند.
  • در اولین باری که درخواست fetch در طول رندر فراخوانده می شود، Next.js برای یافتن پاسخ کش شده به کش داده مراجعه می کند.
  • اگر پاسخ کش شده پیدا شود، بلافاصله برگردانده شده و memoized می شود.
  • اگر پاسخ کش شده یافت نشد، درخواست به منبع داده ارسال می شود، نتیجه در کش داده ذخیره شده و memoized می شود.
  • برای داده های بدون کش (مانند { cache: 'no-store' })، نتیجه همیشه از منبع داده دریافت شده و memoized می شود.
  • صرف نظر از اینکه داده کش شده باشد یا نباشد، درخواست ها همیشه memoized می شوند تا از ایجاد درخواست های تکراری برای داده های مشابه در طول رندرینگ React جلوگیری شود.

تفاوت بین کش داده و Memoization درخواست

در حالی که هر دو مکانیزم کش با استفاده مجدد از داده های کش شده به بهبود عملکرد کمک می کنند، کش داده در تمام درخواست ها و استقرارها ماندگار است، در حالی که memoization درخواست فقط در طول عمر یک درخواست دوام دارد.

با memoization، تعداد درخواست های تکراری در همان گذر رندر که باید از مرز شبکه از سرور رندر به سرور کش داده (مانند CDN یا Edge Network) یا منبع داده (مانند پایگاه داده یا CMS) عبور کنند را کاهش می دهیم. با کش داده، تعداد درخواست‌های انجام‌شده به منبع اصلی داده خود را کاهش می‌دهیم.

مدت زمان

کش داده در تمام درخواست ها و استقرارها ماندگار است مگر اینکه آن را اعتبارسنجی مجدد کنید یا انصراف دهید.

اعتبارسنجی مجدد

داده های کش شده را می توان به دو روش اعتبارسنجی مجدد کرد:

  • اعتبارسنجی مجدد مبتنی بر زمان: داده ها را پس از گذشت مدت زمان معینی و ارسال درخواست جدید اعتبارسنجی مجدد کنید. این برای داده هایی که به ندرت تغییر می کنند و تازگی آنها به اندازه حساس نیست مفید است.
  • اعتبارسنجی مجدد بر اساس تقاضا: داده ها را بر اساس یک رویداد (مانند ارسال فرم) اعتبارسنجی مجدد کنید. اعتبارسنجی مجدد بر اساس تقاضا می تواند از رویکرد مبتنی بر برچسب یا مبتنی بر مسیر برای اعتبارسنجی مجدد گروه های داده به طور همزمان استفاده کند. این زمانی مفید است که می‌خواهید مطمئن شوید آخرین داده‌ها در اسرع وقت نمایش داده می‌شوند (برای مثال، هنگامی که محتوا از سیستم مدیریت محتوای بدون رابط کاربری شما به‌روزرسانی می‌شود).

اعتبارسنجی مجدد مبتنی بر زمان

برای اعتبارسنجی مجدد داده ها در یک فاصله زمانی، می توانید از گزینه next.revalidate دستور fetch برای تنظیم طول عمر کش یک منبع (بر حسب ثانیه) استفاده کنید.

// Revalidate at most every hour
fetch('https://...', { next: { revalidate: 3600 } })

همچنین، می‌توانید از گزینه‌های پیکربندی بخش مسیر برای پیکربندی تمام درخواست‌های fetch در یک بخش یا برای مواردی که قادر به استفاده از fetch نیستید، استفاده کنید.

نحوه عملکرد اعتبارسنجی مجدد مبتنی بر زمان


نموداری که نشان می‌دهد اعتبارسنجی مجدد مبتنی بر زمان چگونه کار می‌کند، پس از دوره اعتبارسنجی مجدد، داده‌های قدیمی برای اولین درخواست برگردانده می‌شوند، سپس داده‌ها مجدداً اعتبارسنجی می‌شوند.نموداری که نشان می‌دهد اعتبارسنجی مجدد مبتنی بر زمان چگونه کار می‌کند، پس از دوره اعتبارسنجی مجدد، داده‌های قدیمی برای اولین درخواست برگردانده می‌شوند، سپس داده‌ها مجدداً اعتبارسنجی می‌شوند.
  • اولین باری که یک درخواست fetch با revalidate فراخوانی می‌شود، داده‌ها از منبع داده خارجی واکشی شده و در کش داده Data Cache ذخیره می‌شوند.
  • هر درخواستی که در بازه زمانی مشخص شده (به عنوان مثال 60 ثانیه) فراخوانده شود، داده کش شده را برمیگرداند.
  • بعد از بازه زمانی تعیین شده، درخواست بعدی همچنان داده کش شده (که حالا کهنه شده است) را برمیگرداند.
    • Next.js اعتبارسنجی مجدد داده را در پس زمینه آغاز خواهد کرد.
    • زمانی که داده با موفقیت دریافت شد، Next.js کش داده را با داده تازه به روز رسانی می کند.
    • اگر اعتبارسنجی مجدد در پس زمینه با شکست مواجه شود، داده قبلی بدون تغییر باقی خواهد ماند.

این مشابه رفتار stale-while-revalidate (opens in a new tab) است.

اعتبارسنجی مجدد بر اساس تقاضا

داده را می توان بر اساس مسیر (revalidatePath) یا برچسب tag کش (revalidateTag) به صورت درخواستی اعتبارسنجی مجدد کرد.

نحوه عملکرد اعتبارسنجی مجدد بر اساس تقاضا


نموداری که نشان می‌دهد اعتبار مجدد درخواستی چگونه کار می‌کند، کش داده‌ها پس از درخواست اعتبارسنجی مجدد با داده‌های تازه به‌روزرسانی می‌شود.نموداری که نشان می‌دهد اعتبار مجدد درخواستی چگونه کار می‌کند، کش داده‌ها پس از درخواست اعتبارسنجی مجدد با داده‌های تازه به‌روزرسانی می‌شود.
  • در اولین باری که درخواست fetch فراخوانده می شود، داده از منبع داده خارجی دریافت شده fetched و در کش داده ذخیره می شود.
  • هنگامی که اعتبارسنجی مجدد بر اساس درخواست آغاز می شود triggered، موارد کش مربوطه از کش حذف خواهند شد.
    • این با اعتبارسنجی مبتنی بر زمان که داده کهنه را تا زمان دریافت داده تازه در کش نگه می دارد، متفاوت است.
  • در دفعه بعدی که درخواستی انجام می شود، دوباره خطای کش MISS رخ خواهد داد و داده از منبع داده خارجی دریافت شده و در کش داده ذخیره می شود.

انصراف دادن

برای فراخوانی های تک به تک داده، می توانید با تنظیم گزینه cache روی no-store، امکان کش شدن را لغو کنید. این به این معنی است که هر زمان fetch فراخوانده شود، داده دریافت خواهد شد.

// Opt out of caching for an individual `fetch` request
fetch(`https://...`, { cache: 'no-store' })

همچنین، می توانید از گزینه های Route Segment Config برای غیرفعال کردن کش برای یک بخش مسیر خاص استفاده کنید. این بر تمام درخواست های داده در بخش مسیر، از جمله کتابخانه های شخص ثالث تأثیر خواهد گذاشت.

// Opt out of caching for all data requests in the route segment
export const dynamic = 'force-dynamic'

توجه: کش داده در حال حاضر فقط در pages/routes در دسترس است، نه در میان افزار. هر فراخوانی fetch که داخل میان افزار شما انجام شود به طور پیش فرض کش نخواهد شد.

کش داده Vercel
اگر اپلیکیشن Next.js شما روی Vercel توسعه داده شده است، توصیه می کنیم برای درک بهتر ویژگی های خاص Vercel، مستندات کش داده Vercel (opens in a new tab) را مطالعه کنید.

کش کامل مسیر Full Route Cache

اصطلاحات مرتبط:
ممکن است با اصطلاحات "بهینه‌سازی استاتیک خودکار Automatic Static Optimization"، "تولید سایت استاتیک Static Site Generation" یا "رندر استاتیک Static Rendering" مواجه شوید که به صورت متقابل برای اشاره به فرآیند رندر و کش کردن مسیرهای برنامه شما در زمان ساخت استفاده می شوند.

Next.js به طور خودکار مسیرها را در زمان ساخت build رندر و کش می کند. این یک بهینه سازی است که به شما امکان می دهد مسیر کش شده را به جای رندر روی سرور برای هر درخواست ارائه دهید، در نتیجه بارگذاری سریعتر صفحه را به همراه دارد.

برای درک نحوه عملکرد کش کامل مسیر، مفید است که به نحوه مدیریت رندر توسط React و نحوه کش کردن نتیجه توسط Next.js نگاه کنید:

1. رندرینگ React روی سرور

در سرور، Next.js از API های React برای هماهنگ سازی رندر استفاده می کند. کار رندر به تکه هایی (chunks) تقسیم می شود: بر اساس بخش های مسیر جداگانه و مرزهای Suspense.

هر تکه (chunk) در دو مرحله رندر می شود:

  1. React، کامپوننت های سرور را به یک فرمت داده ویژه به نام React Server Component Payload که برای استریمینگ بهینه شده است، رندر می کند.
  2. Next.js از React Server Component Payload و دستورالعمل های جاوا اسکریپت کامپوننت های سمت کلاینت برای رندر HTML روی سرور استفاده می کند.

این به این معناست که ما نیازی به انتظار برای اتمام همه‌ی رندرها قبل از کش کردن کار یا ارسال پاسخ نداریم. به جای آن، می‌توانیم یک پاسخ را به عنوان کار انجام شده به صورت پیوسته stream ارسال کنیم.

React Server Component Payload چیست؟

React Server Component Payload یک نمایش باینری فشرده از درخت کامپوننت های سرور رندر شده React است. این توسط React روی کلاینت برای به روز رسانی DOM مرورگر استفاده می شود. React Server Component Payload حاوی موارد زیر است:

  • نتیجه رندر شده کامپوننت های سرور
  • محل‌های قرارگیری برای رندر کردن کامپوننت‌های کلاینت و ارجاع به فایل‌های جاوااسکریپت آن‌ها
  • هرگونه props که از یک سرور کامپوننت به یک کلاینت کامپوننت منتقل شود

برای کسب اطلاعات بیشتر، مستندات سرور کامپوننت ها را ببینید.

2. کش کردن Next.js روی سرور (کش کامل مسیر)


رفتار پیش‌فرض کش کامل مسیر، نشان می‌دهد که چگونه React Server Component Payload و HTML برای مسیرهای رندر شده به صورت ایستا در سرور ذخیره می‌شوند.رفتار پیش‌فرض کش کامل مسیر، نشان می‌دهد که چگونه React Server Component Payload و HTML برای مسیرهای رندر شده به صورت ایستا در سرور ذخیره می‌شوند.

رفتار پیش فرض Next.js این است که نتیجه رندر شده (React Server Component Payload و HTML) یک مسیر را روی سرور کش کند. این در مورد مسیرهای رندر شده به صورت استاتیک در زمان ساخت build یا در طول اعتبارسنجی مجدد اعمال می شود.

3. Hydration و Reconciliation React روی کلاینت

در زمان درخواست، روی کلاینت:

  1. HTML برای نمایش فوری یک پیش نمایش اولیه غیر تعاملی سریع از کامپوننت های کلاینت و سرور استفاده می شود.
  2. از React Server Component Payload برای تطبیق درخت های کامپوننت های رندر شده سرور و کاربر و به روز رسانی DOM استفاده می شود.
  3. از دستورالعمل های جاوا اسکریپت برای hydrate (opens in a new tab) کردن کامپوننت های کلاینت و تعاملی کردن برنامه استفاده می شود.

4. کش کردن Next.js در کلاینت (کش مسیریاب Router Cache)

React Server Component Payload در کش مسیریاب Router Cache کلاینت ذخیره می‌شود - یک کش جداگانه در حافظه، تقسیم شده بر اساس بخش های مسیر جداگانه. این کش مسیریاب برای بهبود تجربهٔ پیمایش با ذخیره کردن مسیرهای قبلی بازدید شده و پیش‌بارگیری مسیرهای آینده استفاده می‌شود.

5. پیمایش های بعدی

در پیمایش های بعدی یا در حین پیش بارگیری Next.js بررسی می کند که آیا React Server Component Payload در کش مسیریاب ذخیره شده است یا خیر. در صورت وجود، ارسال درخواست جدید به سرور را رد می کند.

اگر بخش‌های مسیر در کش نباشند، Next.js، React Server Components Payload را از سرور دریافت می‌کند و کش مسیریاب را روی کلاینت پر می‌کند.

رندر کردن استاتیک و پویا

اینکه یک مسیر در زمان ساخت کش شود یا نه بستگی به این دارد که به صورت استاتیک یا پویا رندر شود. مسیرهای استاتیک به طور پیش فرض کش می شوند، در حالی که مسیرهای پویا در زمان درخواست رندر می شوند و کش نمی شوند.

این نمودار تفاوت بین مسیرهای رندر شده به صورت استاتیک و پویا را با داده های کش شده و کش نشده نشان می دهد:


چگونه رندر استاتیک و پویا بر حافظه پنهان مسیر کامل تأثیر می گذارد. مسیرهای استاتیک در زمان ساخت یا پس از تأیید مجدد داده ها در حافظه پنهان ذخیره می شوند، در حالی که مسیرهای پویا هرگز ذخیره نمی شوند.چگونه رندر استاتیک و پویا بر حافظه پنهان مسیر کامل تأثیر می گذارد. مسیرهای استاتیک در زمان ساخت یا پس از تأیید مجدد داده ها در حافظه پنهان ذخیره می شوند، در حالی که مسیرهای پویا هرگز ذخیره نمی شوند.

درباره رندر کردن استاتیک و پویا بیشتر بیاموزید.

مدت زمان

به طور پیش فرض، کش کامل مسیر پایدار است. این به این معنی است که خروجی رندر در بین درخواست های کاربر کش می شود.

ابطال

دو روش برای ابطال کش کامل مسیر Full Route Cache وجود دارد:

  • اعتبارسنجی مجدد داده: اعتبارسنجی مجدد کش داده، به نوبه خود کش مسیریاب را با رندر مجدد کامپوننت ها روی سرور و کش کردن خروجی رندر جدید، ابطال می کند.
  • استقرار مجدد Redeploying: برخلاف کش داده که در تمام استقرارها باقی می ماند، کش کامل مسیر در استقرارهای جدید پاک می شود.

انصراف دادن

می توانید با استفاده از روش های زیر از کش کامل مسیر جلوگیری کنید یا به عبارت دیگر، کامپوننت ها را برای هر درخواست ورودی به طور پویا رندر کنید:

  • استفاده از یک تابع داینامیک: این کار مسیر را از کش کامل مسیر خارج می کند و آن را در زمان درخواست به طور پویا رندر می کند. کش داده همچنان قابل استفاده است.
  • استفاده از گزینه های پیکربندی بخش مسیر dynamic = 'force-dynamic' یا revalidate = 0: این کار کش کامل مسیر و کش داده را دور می زند. به این معنی که کامپوننت ها برای هر درخواست ورودی به سرور رندر می شوند و داده ها دریافت می شوند. کش مسیریاب همچنان اعمال می شود زیرا یک کش سمت کلاینت است.
  • غیرفعال کردن کش داده: اگر یک مسیر دارای درخواست fetch باشد که کش نشده باشد، این کار مسیر را از کش کامل مسیر خارج می کند. داده ها برای درخواست fetch خاص برای هر درخواست ورودی دریافت می شوند. سایر درخواست های fetch که از کش کردن خودداری نمی کنند، همچنان در کش داده کش می شوند. این اجازه می دهد تا ترکیبی از داده های کش و غیر کش را ایجاد کنید.

کش مسیرباب Router Cache

اصطلاحات مرتبط:

ممکن است با نام های کش سمت کاربر Client-side Cache یا کش پیش بارگذاری Prefetch Cache برای کش مسیریاب (Router Cache) مواجه شوید. در حالی که کش پیش بارگذاری به بخش های مسیر پیش بارگذاری شده اشاره دارد، کش سمت کاربر به کل کش مسیریاب، که شامل بخش های بازدید شده و پیش بارگذاری شده، اشاره دارد. این کش به طور خاص برای Next.js و کامپوننت های سرور اعمال می شود و با bfcache (opens in a new tab) مرورگر متفاوت است، اما نتیجه مشابهی دارد.

Next.js دارای یک کش سمت کلاینت در حافظه است که React Server Component Payload را برای مدت زمان یک نشست کاربری، بر اساس بخش های مسیر جداگانه ذخیره می کند. این کش مسیریاب (Router Cache) نامیده می شود.

نحوه کار کش مسیریاب


نحوه کار کش مسیریاب برای مسیرهای استاتیک و پویا، نشان دادن MISS و HIT برای پیمایش های اولیه و بعدی.نحوه کار کش مسیریاب برای مسیرهای استاتیک و پویا، نشان دادن MISS و HIT برای پیمایش های اولیه و بعدی.

با حرکت کاربر بین مسیرها، Next.js بخش های مسیر بازدید شده را کش می کند و مسیرهایی را که کاربر به احتمال زیاد به آنها هدایت می شود (بر اساس کامپوننت های <Link> در نمای viewport آنها) پیش بارگذاری prefetches می کند.

این امر منجر به تجربه پیمایش بهتری برای کاربر می شود:

  • پیمایش فوری به عقب/جلو به دلیل کش شدن مسیرهای بازدید شده. پیمایش سریع به مسیرهای جدید به دلیل پیش بارگذاری و رندر جزئی partial rendering.
  • بین پیمایش ها نیازی به بارگذاری مجدد کامل صفحه نیست و استیت React و استیت مرورگر حفظ می شود.

تفاوت بین کش مسیریاب Router Cache و کش کامل مسیر Full Route Cache:

کش مسیریاب به طور موقت React Server Component Payload را در مرورگر برای مدت زمان یک جلسه کاربری ذخیره می کند، در حالی که کش کامل مسیر به طور مداوم React Server Component Payload و HTML را روی سرور در چندین درخواست کاربر ذخیره می کند.

در حالی که کش کامل مسیر فقط مسیرهای رندر شده به صورت استاتیک را کش می کند، کش مسیریاب برای مسیرهای رندر شده به صورت استاتیک و پویا اعمال می شود.

مدت زمان

کش در حافظه موقت مرورگر ذخیره می شود. دو عامل تعیین می کنند که کش مسیریاب چقدر دوام داشته باشد:

  • نشست: کش در حین پیمایش باقی می ماند. با این حال، در زمان رفرش صفحه پاک می شود.
  • دوره باطل سازی خودکار: کش یک بخش جداگانه پس از مدت زمان مشخصی به طور خودکار باطل می شود. مدت زمان بستگی به نحوه پیش بارگذاری prefetched منبع دارد:
    • پیش بارگذاری پیش فرض (prefetch={null} یا مشخص نشده): 30 ثانیه
    • پیش بارگذاری کامل: (prefetch={true} یا router.prefetch): 5 دقیقه

در حالی که رفرش صفحه همه بخش های کش شده را پاک می کند، دوره باطل سازی خودکار فقط بر روی بخش جداگانه از زمانی که پیش بارگذاری شده است تأثیر می گذارد.

توجه: پشتیبانی آزمایشی برای پیکربندی این مقادیر از نسخه v14.2.0 (opens in a new tab) در دسترس است.

باطل سازی

دو راه برای باطل کردن کش مسیریاب وجود دارد:

  • در یک Server Action:
    • اعتبارسنجی مجدد داده به صورت درخواستی بر اساس مسیر با (revalidatePath) یا برچسب tag کش با (revalidateTag)
    • استفاده از cookies.set یا cookies.delete کش مسیریاب را برای جلوگیری از کهنه شدن مسیرهایی که از کوکی ها استفاده می کنند (به عنوان مثال احراز هویت) باطل می کند.
  • با فراخوانی router.refresh، کش مسیریاب باطل می شود و یک درخواست جدید برای مسیر فعلی به سرور ارسال می شود.

انصراف دادن

انصراف دادن از کش مسیریاب امکان پذیر نیست. با این حال، می توانید آن را با فراخوانی router.refresh، revalidatePath یا revalidateTag (موارد بالا را ببینید) باطل کنید. این کار کش را پاک می کند و یک درخواست جدید به سرور ارسال می کند تا اطمینان حاصل شود که آخرین داده ها نمایش داده می شوند.

همچنین می توانید با تنظیم مقدار prefetch کامپوننت <Link> روی false، از پیش بارگذاری اجتناب کنید. با این حال، این کار همچنان بخش های مسیر را برای 30 ثانیه به طور موقت ذخیره می کند تا امکان پیمایش فوری بین بخش های تو در تو، مانند نوارهای تب، یا پیمایش به عقب و جلو را فراهم کند. مسیرهای بازدید شده همچنان کش می شوند.

تعاملات کش

هنگام پیکربندی مکانیسم های کشینگ مختلف، درک نحوه تعامل آنها با یکدیگر مهم است:

کش داده و کش کامل مسیر

  • اعتبارسنجی مجدد یا خارج شدن از کش داده، کش کامل مسیر را باطل می کند، زیرا خروجی رندر به داده بستگی دارد.
  • باطل سازی یا خارج شدن از کش کامل مسیر، کش داده را تحت تاثیر قرار نمی دهد. شما می توانید مسیری را به صورت پویا رندر کنید که هم داده های کش شده و هم کش نشده داشته باشد. این زمانی مفید است که بیشتر صفحه شما از داده های کش شده استفاده می کند، اما چند کامپوننت دارید که به داده هایی متکی هستند که باید در زمان درخواست فراخوانده شوند. شما می‌توانید به‌صورت پویا رندر کنید بدون نگرانی از تأثیر عملکردی که بازیابی مجدد re-fetching همه داده‌ها به همراه دارد..

کش داده و کش مسیریاب سمت کلاینت

  • اعتبارسنجی مجدد کش داده در یک Route Handler بلافاصله کش مسیریاب را باطل نمی کند زیرا Route Handler به یک مسیر خاص مرتبط نیست. این بدان معناست که کش مسیریاب تا زمان بروزرسانی کامل یا پایان دوره باطل سازی خودکار، همچنان به ارائه بارگذاری قبلی ادامه خواهد داد.
  • برای باطل کردن فوری کش داده و کش مسیریاب، می توانید از revalidatePath یا revalidateTag در یک Server Action استفاده کنید.

APIs

جدول زیر نمای کلی از اینکه چگونه API های Next.js مختلف بر روی کش تاثیر می گذارند ارائه می دهد:

APIکش مسیریابکش کامل مسیرکش دادهکش React
<Link prefetch>کش
router.prefetchکش
router.refreshاعتبارسنجی مجدد
fetchکشکش
fetch options.cacheکش یا انصراف دادن
fetch options.next.revalidateاعتبارسنجی مجدداعتبارسنجی مجدد
fetch options.next.tagsکشکش
revalidateTagاعتبارسنجی مجدد (Server Action)اعتبارسنجی مجدداعتبارسنجی مجدد
revalidatePathاعتبارسنجی مجدد (Server Action)اعتبارسنجی مجدداعتبارسنجی مجدد
const revalidateاعتبارسنجی مجدد یا انصراف دادناعتبارسنجی مجدد یا انصراف دادن
const dynamicکش یا انصراف دادنکش یا انصراف دادن
cookiesاعتبارسنجی مجدد (Server Action)انصراف دادن
headers, searchParamsانصراف دادن
generateStaticParamsکش
React.cacheکش
unstable_cacheکش

<Link>

به طور پیش فرض، کامپوننت <Link> به طور خودکار مسیرها را از کش کامل مسیر پیش بارگذاری می کند و React Server Component Payload را به کش مسیریاب اضافه می کند.

برای غیرفعال کردن پیش بارگذاری، می توانید مقدار prefetch را روی false تنظیم کنید. اما این کار به طور دائم کش را رد نمی کند، بخش مسیر همچنان در زمان بازدید کاربر از مسیر در سمت کلاینت کش می شود.

درباره کامپوننت <Link> بیشتر بیاموزید.

router.prefetch

از گزینه prefetch هوک useRouter می توان برای پیش بارگذاری دستی یک مسیر استفاده کرد. این کار React Server Component Payload را به کش مسیریاب اضافه می کند.

به بخش مرجع API هوک useRouter مراجعه کنید.

router.refresh

از گزینه refresh هوک useRouter می توان برای بروزرسانی دستی یک مسیر استفاده کرد. این کار کش مسیریاب را به طور کامل پاک می کند و یک درخواست جدید برای مسیر فعلی به سرور ارسال می کند. refresh بر کش داده یا کش کامل مسیر تأثیر نمی گذارد.

نتیجه رندر شده در سمت کلاینت در حالی که استیت React و استیت مرورگر حفظ می شود، تطبیق داده می شود.

به بخش مرجع API هوک useRouter مراجعه کنید.

fetch

داده های برگشتی از fetch به طور خودکار در کش داده کش می شوند.

// Cached by default. `force-cache` is the default option and can be omitted.
fetch(`https://...`, { cache: 'force-cache' })

برای گزینه های بیشتر به بخش مرجع API fetch مراجعه کنید.

fetch options.cache

می توانید با تنظیم گزینه cache روی no-store، درخواست های fetch جداگانه داده را از کش کردن داده ها خارج کنید:

// Opt out of caching
fetch(`https://...`, { cache: 'no-store' })

از آنجایی که خروجی رندر به داده بستگی دارد، استفاده از cache: 'no-store' همچنین کش کامل مسیر را برای مسیری که از درخواست fetch در آن استفاده می شود، رد می کند. یعنی مسیر هر درخواست به صورت پویا رندر می شود، اما همچنان می توانید درخواست های داده کش شده دیگری در همان مسیر داشته باشید.

برای گزینه های بیشتر به بخش مرجع API fetch مراجعه کنید.

fetch options.next.revalidate

شما می‌توانید از گزینه next.revalidate در fetch برای تنظیم دوره اعتبارسنجی مجدد (به ثانیه) یک درخواست fetch جداگانه استفاده کنید. این کار کش داده را اعتبارسنجی مجدد می کند که به نوبه خود کش کامل مسیر را اعتبارسنجی مجدد می کند. داده های جدید دریافت می شوند و کامپوننت ها در سرور دوباره رندر می شوند.

// Revalidate at most after 1 hour
fetch(`https://...`, { next: { revalidate: 3600 } })

برای گزینه های بیشتر به بخش مرجع API fetch مراجعه کنید.

fetch options.next.tags و revalidateTag

Next.js دارای یک سیستم تگ گذاری کش برای کش کردن و اعتبارسنجی مجدد داده های دقیق است.

  1. هنگام استفاده از fetch یا unstable_cache، این امکان را دارید که ورودی های کش را با یک یا چند تگ تگ کنید.
  2. سپس می توانید revalidateTag را فراخوانی کنید تا ورودی های کش مرتبط با آن تگ را پاک کنید.

برای مثال، می توانید هنگام دریافت داده یک تگ تنظیم کنید:

// Cache data with a tag
fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } })

سپس برای پاک کردن ورودی کش از revalidateTag با یک تگ استفاده کنید:

// Revalidate entries with a specific tag
revalidateTag('a')

دو جا وجود دارد که می توانید از revalidateTag استفاده کنید، بسته به اینکه به چه چیزی می خواهید برسید:

  1. Route Handlers - برای اعتبارسنجی مجدد داده ها در پاسخ به یک رویداد شخص ثالث (به عنوان مثال وب هوک). این کار کش مسیریاب را بلافاصله باطل نمی کند زیرا Route Handler به یک مسیر خاص مرتبط نیست.
  2. Server Actions - برای اعتبارسنجی مجدد داده ها پس از یک اکشن کاربر (به عنوان مثال ارسال فرم). این کار کش مسیریاب را برای مسیر مرتبط باطل می کند.

revalidatePath

revalidatePath به شما امکان می دهد داده ها را به صورت دستی اعتبارسنجی مجدد کنید و بخش های مسیر را در زیر یک مسیر خاص در یک عملیات واحد دوباره رندر کنید. فراخوانی متد revalidatePath کش داده را اعتبارسنجی مجدد می کند که به نوبه خود کش کامل مسیر را باطل می کند.

revalidatePath('/')

دو جا وجود دارد که می توانید از revalidatePath استفاده کنید، بسته به اینکه به چه چیزی می خواهید برسید:

  1. Route Handlers - برای اعتبارسنجی مجدد داده ها در پاسخ به یک رویداد شخص ثالث (به عنوان مثال وب هوک).
  2. Server Actions - برای اعتبارسنجی مجدد داده ها پس از تعامل کاربر (به عنوان مثال ارسال فرم، کلیک روی یک دکمه).

برای اطلاعات بیشتر به بخش مرجع API revalidatePath مراجعه کنید.

revalidatePath در مقابل router.refresh:

فراخوانی router.refresh کش مسیریاب را پاک می کند و بخش های مسیر را بدون باطل کردن کش داده یا کش کامل مسیر در سرور دوباره رندر می کند.

تفاوت این است که revalidatePath باعث پاکسازی کش داده و کش کامل مسیر می شود، در حالی که router.refresh() به دلیل اینکه یک API سمت کلاینت است، کش داده و کش کامل مسیر را تغییر نمی دهد.

توابع داینامیک

استفاده از توابع پویا مانند cookies و headers و همچنین prop searchParams در صفحات، باعث خروج مسیر از کش کامل مسیر و در نتیجه رندر پویای مسیر می شود.

cookies

Using cookies.set or cookies.delete in a Server Action invalidates the Router Cache to prevent routes that use cookies from becoming stale (e.g. to reflect authentication changes). استفاده از cookies.set یا cookies.delete در یک اکشن سرور، کش مسیریاب را باطل می کند تا از کهنه شدن مسیرهایی که از کوکی ها استفاده می کنند (به عنوان مثال برای اعمال تغییرات احراز هویت) جلوگیری کند.

مرجع API cookies را ببینید.

گزینه های پیکربندی بخش مسیر

گزینه‌های پیکربندی بخش مسیر می‌توانند برای نادیده گرفتن پیش‌فرض‌های بخش مسیر یا زمانی که نمی‌توانید از API fetch استفاده کنید (مانند کاربردهایی که از کتابخانه‌های دیتابیس یا شخص ثالث استفاده می‌کنید) مورد استفاده قرار گیرند.

استفاده از گزینه های پیکربندی بخش مسیر زیر باعث خروج از کش داده و کش کامل مسیر می شود:

  • const dynamic = 'force-dynamic'
  • const revalidate = 0

برای گزینه های بیشتر به مستندات پیکربندی بخش مسیر مراجعه کنید.

generateStaticParams

برای dynamic segments (مثلاً app/blog/[slug]/page.js)، مسیرهایی که توسط generateStaticParams ارائه می شوند، در زمان ساخت در کش کامل مسیر کش می شوند. در زمان درخواست، Next.js همچنین مسیرهایی را که در زمان ساخت شناخته نشده بودند، اولین بار که بازدید می شوند، کش می کند.

شما می‌توانید با استفاده از گزینه export const dynamicParams = false در یک بخش مسیر، در زمان درخواست، کش کردن را غیرفعال کنید. هنگامی که از این گزینه پیکربندی استفاده می شود، فقط مسیرهای ارائه شده توسط generateStaticParams ارائه می شود و سایر مسیرها 404 یا مطابقت دارند (در مورد catch-all routes).

مرجع API generateStaticParams را ببینید.

تابع cache React

تابع cache React به شما امکان می دهد مقدار بازگشتی یک تابع را به خاطر بسپارید memoize، در نتیجه می توانید همان تابع را چندین بار فراخوانی کنید در حالی که فقط یک بار آن را اجرا می کنید.

از آنجایی که درخواست های fetch به طور خودکار به خاطر سپرده memoized می شوند، نیازی به قرار دادن آنها در cache React نیست. با این حال، می توانید از کش برای به خاطر سپردن memoize دستی درخواست های داده برای موارد استفاده ای که API fetch مناسب نیست استفاده کنید، به عنوان مثال برخی از کلاینت های پایگاه داده، کلاینت های CMS یا کلاینت های GraphQL.

utils/get-item.ts
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
})