Cache Components در Next.js 16؛ کش دیگه پیشفرض نیست
خلاصهٔ کاملتر
این مطلب رو آرورا شارف نوشته که تو تیم Next.js در Vercel کار میکنه. نقطهٔ شروعش یه درد آشناست: تو App Router قدیمی، کش پیشفرض روشن بود و تقریباً تو کد دیده نمیشد، برای همین وقتت صرف این میشد که بفهمی چرا یه روت کش شده که نباید میشد، یا چرا داینامیک اجرا شده که انتظارش رو نداشتی.
Cache Components که با Next.js 16 اومده این پیشفرض رو برعکس کرده: داده داینامیکه و هر ریکوئست از نو اجرا میشه، مگه خودت با "use cache" کشش کنی. فهرست محصولات برای همه یکیه پس میشه کشش کرد، ولی سبد خرید کاربر لاگینکرده باید هر بار تازه اجرا بشه. روشنکردنش یه فلگ سادهست، cacheComponents: true، که جای گزینههای قدیمی dynamicIO و useCache و ppr رو هم میگیره — و چون پیشفرض کل اپ رو یکجا عوض میکنه، تو پروژهٔ موجود یه مهاجرته نه یه سوییچ سریع.
به گفتهٔ نویسنده، حالا هر تکه دادهای که روت منتظرشه باید یکی از سه سرنوشت رو داشته باشه: استریم با (کاربر فوراً fallback رو میبینه و محتوا بعداً میرسه)، کش با "use cache" (نتیجه بین ریکوئستها بازاستفاده میشه)، یا بلاک با export const instant = false (روت صبر میکنه تا سرور تموم کنه). گزینهٔ سوم عملاً راه فراره؛ مثلاً برای پست بلاگی که نمیخوای اسکلتون توش بپره.
تو مثال فروشگاه، کاتالوگ محصولات از صفحه جدا و به یه کامپوننت Products منتقل میشه تا "use cache" جا برای نشستن داشته باشه، و پیشنهادهای شخصیسازیشده پشت یه Suspense استریم میشن:
async function Products() {
'use cache';
const products = await getProducts();
return <ProductGrid products={products} />;
}نتیجه یه صفحهٔ دولایهست: هدینگ و گرید محصولات از قبل رندر و بهعنوان پوسته بلافاصله فرستاده میشن، پیشنهادها پشت اسکلتون استریم میشن. چون پوسته به ریکوئست وابسته نیست میشه روی CDN کشش کرد و نزدیک کاربر سرو کرد. همین تقسیم دولایه همون Partial Prerendering ـه که قبلاً یه فلگ آزمایشی جدا بود و حالا بدون تنظیم اضافه، مدل رندر پیشفرضه.
خود "use cache" سه سطح داره: بالای فایل (همهٔ اکسپورتها کش میشن)، روی یه کامپوننت، یا روی یه تابع async معمولی. نویسنده میگه سطح تابع معمولاً مفیدترینه، چون اگه چند صفحه getProducts رو صدا بزنن همه یه ورودی کش مشترک دارن و کامپوننتها اصلاً لازم نیست بدونن چیزی کش شده. کلید کش رو هم خودت نمینویسی: Next.js از هویت تابع و آرگومانهای سریالایزشده میسازتش، پس هر آرگومان ورودی کش خودش رو داره — و متغیرهای closure هم جزو کلید حساب میشن.
برای طول عمر، cacheLife رو داخل اسکوپ کش صدا میزنی؛ هر پروفایل سه عدد داره: stale (چقدر کلاینت بدون پرسیدن از سرور بازاستفاده کنه)، revalidate (فاصلهٔ تازهسازی پسزمینه) و expire (سقف سخت). پروفایلهای آماده از seconds تا max هستن و اگه هیچکدوم جا نیفتاد میتونی عدد دقیق به ثانیه بدی. برای باطلکردن هدفمند هم cacheTag هست: جایی که داده رو میخونی تگ میزنی و موقع نوشتن پاکش میکنی:
export async function getProducts() {
'use cache';
cacheLife('hours');
cacheTag('products');
return db.product.findMany();
}دو تغییر تو Next.js 16 اینجا مهمن: revalidateTag حالا آرگومان دوم میگیره — یه پروفایل cacheLife که رفتار ورودی بعد از باطلشدن رو تعیین میکنه — و یه updateTag تازه برای Server Actionها اضافه شده. فرقشون زمانبندیه: updateTag ورودی رو منقضی و قبل از برگشتن پاسخ دوباره میخونه، پس کسی که تغییر رو ثبت کرده همون لحظه نتیجه رو میبینه؛ revalidateTag تگ رو پاک و در پسزمینه تازه میکنه. اولی برای فلوهای «نتیجهٔ کار خودت رو ببین» و دومی وقتی یه تأخیر کوتاه اشکالی نداره.
نکات کلیدی:
- Cache Components در Next.js 16 پیشفرض رو برعکس کرده: داده داینامیکه مگه صریحاً کشش کنی
- فلگ cacheComponents: true جایگزین dynamicIO، useCache و ppr شده و فعالکردنش یه مهاجرته
- هر داده یکی از سه راه رو میگیره: استریم با Suspense، کش با "use cache"، یا بلاک با instant = false
- Partial Prerendering حالا مدل رندر پیشفرضه، نه یه فلگ آزمایشی
- کلید کش از هویت تابع، آرگومانهای سریالایزشده و متغیرهای closure ساخته میشه
- cacheLife سه مقدار stale/revalidate/expire میده و cacheTag بههمراه revalidateTag و updateTag باطلسازی هدفمند




