spinny:~/writing $ vim nextjs-16-cache-components.md
1~2برای سالها یکی از آزاردهندهترین سوالات در Next.js این بود: "این صفحه ثابت است یا پویا؟". این یک سوال ساده به نظر می رسد، تا زمانی که یک تماس به `cookies()`، یک `fetch` با گزینه های مختلف، یک سرویس گیرنده پایگاه داده، یک CMS، یک سبد خرید، یا یک قطعه از محتوای سفارشی اضافه کنید.3~4Next.js 16 جالب است زیرا سعی می کند این مکالمه را کمتر مرموز کند. این پیچیدگی را از بین نمیبرد، اما مدل ذهنی را تغییر میدهد: مسیرها بهطور پیشفرض پویا هستند، حافظه پنهان در جایی که لازم است خود را اعلام میکند، و `Suspense` راهی طبیعی برای ترکیب پوستههای سریع با قطعاتی میشود که تازه میمانند.5~6ویژگی قابل درک، Cache Components است. Stable Turbopack، React Compiler، `proxy.ts`، و API های جدید باطل اهمیت دارند، اما حول همین مشکل می چرخند: ساخت برنامه های سریع بدون نیاز به حدس زدن چارچوب در پشت صحنه چه تصمیمی گرفته است.7~8## چون این چیز مهمه9~10در یک برنامه واقعی، شما فقط "صفحات ثابت" و "صفحات پویا" ندارید. شما قطعات مختلف با نیازهای متفاوت دارید.11~12برگه محصول ممکن است چند بار در روز تغییر کند. قیمت ممکن است بیشتر تغییر کند. در دسترس بودن باید تقریباً زنده باشد. نام کاربری شخصی است. نظرات را می توان به صورت جریانی پخش کرد. نوار کناری می تواند پایدار باشد. سبد خرید ندارد.13~14اگر همه چیز را به عنوان یک واحد در نظر بگیرید، همیشه در یکی از دو حالت افراطی قرار می گیرید:15~16- حافظه پنهان تهاجمی و خطر دیدن داده های قدیمی؛17- رندر پویا در همه جا و عملکرد بدتر از حد لازم.18~19Cache Components دقیقاً برای جلوگیری از این انتخاب اشتباه عمل می کند.20~21## مدل در عمل22~23با `cacheComponents: true`، می توانید با استفاده از `"use cache"` آنچه را که در حافظه پنهان است، اعلام کنید. سپس می توانید مدت زمان و برچسب ها را با `cacheLife()` و `cacheTag()` مرتبط کنید. قطعات دینامیک پویا باقی می مانند و با `Suspense` قابل جداسازی هستند.24~25```mermaid26flowchart TD27 Request[درخواست کاربر] --> Shell[پوسته ذخیره شده]28 Request --> Dynamic[مقاطع پویا]29 Shell --> FirstPaint[اولین محتوای سریع]30 Dynamic --> Stream[در حال پخش در داخل Suspense]31 Stream --> Complete[صفحه کامل]32```33~34تنظیمات کوچک است:35~36```typescript37// next.config.ts38import type { NextConfig } from 'next';39~40const nextConfig: NextConfig = {41 cacheComponents: true,42};43~44export default nextConfig;45```46~47تغییر بزرگ در پیکربندی نیست. این در نحوه شروع نوشتن اجزاست.48~49```tsx50// app/products/[slug]/page.tsx51import { Suspense } from 'react';52import { cacheLife, cacheTag } from 'next/cache';53~54async function getProduct(slug: string) {55 'use cache';56~57 cacheLife('hours');58 cacheTag(`product:${slug}`);59~60 return db.product.findUnique({ where: { slug } });61}62~63async function ProductDetails({ slug }: { slug: string }) {64 const product = await getProduct(slug);65~66 return (67 <section>68 <h1>{product.name}</h1>69 <p>{product.description}</p>70 </section>71 );72}73~74async function LiveInventory({ slug }: { slug: string }) {75 const inventory = await db.inventory.findFirst({ where: { slug } });76 return <p>{inventory.quantity} pezzi disponibili</p>;77}78~79export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {80 const { slug } = await params;81~82 return (83 <>84 <ProductDetails slug={slug} />85 <Suspense fallback={<p>Controllo disponibilità...</p>}>86 <LiveInventory slug={slug} />87 </Suspense>88 </>89 );90}91```92~93لازم نیست صفحه تماماً کش یا تماماً پویا باشد. برگه محصول می تواند سریع و قابل استفاده مجدد باشد. موجودی می تواند تازه بماند. کاربر بلافاصله چیزی را می بیند، بدون اینکه منتظر کندترین قسمت باشد.94~95## `use cache` مستندات اجرایی است96~97چیزی که من در مورد `"use cache"` دوست دارم این است که شما را مجبور می کند که قصدی را صریح بیان کنید. هنگامی که یک تابع را می خوانید، بلافاصله متوجه می شوید که شخصی تصمیم گرفته است: "این داده ها قابل استفاده مجدد هستند".98~99به خصوص زمانی که از `fetch` استفاده نمی کنید مفید است. بسیاری از برنامه ها داده های Prisma، Drizzle، SDK های داخلی، کلاینت های CMS یا توابع سرویس را می خوانند. در آن موارد، استدلال قدیمی فقط بر اساس گزینه های `fetch` کافی نبود.100~101یک قانون سرانگشتی:102~103- محتوای cachea نسبتاً پایدار است.104- از برچسب های دانه ای استفاده کنید.105- مجوزهای پویا، جلسات، سبد خریدها، اعلانها و وضعیتهای تراکنش را ترک میکند.106- قطعات کند را داخل `Suspense` قرار دهید.107- قبل از گفتن "ما عملکرد را بهبود بخشیم" اندازه گیری کنید.108~109## بدون دور ریختن همه چیز باطل کنید110~111کش تنها زمانی مفید است که بتوانید آن را به طور دقیق به روز کنید. در اینجا `cacheTag`، `revalidateTag` و `updateTag` مهم می شوند.112~113مثال:114~115```typescript116'use server';117~118import { updateTag } from 'next/cache';119~120export async function updateProductName(productId: string, name: string) {121 await db.product.update({122 where: { id: productId },123 data: { name },124 });125~126 updateTag(`product:${productId}`);127}128```129~130جزئیات مهم برچسب است. `product:${productId}` یک مرز دقیق را نشان می دهد. `products` به یک سطل بزرگ می گوید. در ابتدا سطل بزرگ راحت است. بعد از چند ماه این دلیلی می شود که نیمی از یک برنامه را برای تغییر عنوان باطل کنید.131~132## توربوپک پایدار: بخشی که هر روز می شنوید133~134Next.js 16 Turbopack را برای توسعه و ساخت به مرکز می آورد. این شاعرانهترین ویژگی نیست، اما آن چیزی است که در حین کار احساس میکنید: سروری که زودتر شروع به کار میکند، سریعتر بهروزرسانی میشود، ساختهایی که احساس یک استراحت اجباری قهوه را ندارند.135~136با این حال، من یک پایگاه کد پر از پلاگین های سفارشی را با چشمان بسته منتقل نمی کنم. من بررسی می کنم:137~138- ساخت محلی؛139- واردات غیر استاندارد؛140- MDX، SVG و CSS؛141- افزونه های Webpack باقی مانده است.142- صفحات انتقادی؛143- تفاوت در زمان ساخت144~145برای پروژه های جدید، از حالت پیش فرض شروع می کنم. برای افراد بالغ، من یک مهاجرت سنجیده انجام می دهم.146~147## React Compiler: حذف نویز، نه فکر148~149React Compiler 1.0 پایدار است و Next.js 16 آن را با `reactCompiler` پشتیبانی می کند. وعده کاهش مقدار زیادی از یادداشت دستی است: کمتر `memo`، کمتر `useMemo`، کمتر `useCallback` استفاده شده "برای ایمنی".150~151```typescript152// next.config.ts153import type { NextConfig } from 'next';154~155const nextConfig: NextConfig = {156 reactCompiler: true,157};158~159export default nextConfig;160```161~162من با آن مانند یک گرد و غبار جادویی رفتار نمی کنم. کامپایلر زمانی کمک می کند که کد به خوبی از قوانین React پیروی کند. اگر اجزاء دارای عوارض جانبی عجیب، جهش های پنهان یا قلاب های بد استفاده شده باشند، ابتدا باید اصلاح شوند.163~164روش سالم امتحان کردن:165~1661. به روز رسانی `eslint-plugin-react-hooks`؛1672. رفع تخلفات واقعی؛1683. آن را در یک منطقه کنترل شده فعال کنید.1694. اندازه گیری زمان ساخت و رفتار.1705. ذخیره سازی دستی را فقط زمانی حذف کنید که دیگر مورد نیاز نباشد.171~172هدف پاک کردن هر `useMemo` نیست. هدف این است که نوشتن یادداشت پیشگیرانه را متوقف کنیم زیرا از رندر می ترسیم.173~174## `proxy.ts` و مرز شبکه175~176`middleware.ts` قدیمی به `proxy.ts` تبدیل می شود. این یک تغییر نام است، اما منطقی است: آن فایل در مرز درخواست قرار میگیرد، یک میانافزار عمومی سنتی به سبک باطن نیست.177~178```typescript179// proxy.ts180import { NextRequest, NextResponse } from 'next/server';181~182export default function proxy(request: NextRequest) {183 const isLoggedIn = Boolean(request.cookies.get('session'));184~185 if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {186 return NextResponse.redirect(new URL('/login', request.url));187 }188~189 return NextResponse.next();190}191```192~193قانون اینجا ساده است: آن را کوچک نگه دارید. تغییر مسیر، مسیریابی احراز هویت، هدرها، بازنویسی های ضروری. اگر شروع به احساس یک باطن دوم کند، احتمالاً کار زیادی انجام می دهد.194~195## واقعا چقدر مهاجرت میکردم196~197من همه ویژگی ها را به یکباره روشن نمی کنم. من این کار را انجام می دهم:198~1991. من Next، React و React DOM را به روز می کنم.2002. من کد مد رسمی را راه اندازی می کنم.2013. من تغییرات شکستن را در `params`، `searchParams`، `cookies()`، `headers()` و `draftMode()` اصلاح می کنم.2024. من `middleware.ts` را به `proxy.ts` مهاجرت می کنم.2035. من ساخت و صفحات بحرانی را بررسی می کنم.2046. من Cache Components را در بخشی فعال می کنم که کش در حال حاضر اصطکاک ایجاد می کند.2057. من قراردادهایی را برای برچسب ها و باطل کردن تعریف می کنم.2068. من React Compiler را جداگانه امتحان می کنم.2079. مقایسه معیارهای قبل و بعد208~209مهاجرت خوب آن چیزی نیست که از همه ویژگی های جدید استفاده کند. این چیزی است که رفتار برنامه را خواناتر می کند.210~211## آنچه در طرز فکر تغییر می کند212~213مفیدترین چیز در مورد Next.js 16 این است که شما را مجبور می کند تا اهداف را بهتر نامگذاری کنید. یک تابع فقط "دریافت محصول از پایگاه داده" نیست. این "محصول را دریافت کنید، می توانم آن را برای ساعت ها کش کنم، با این برچسب آن را باطل می کنم". کامپوننت فقط "رندر صفحه" نیست. این "این پوسته سریع است، این قطعه شخصی است، این جریان پخش می شود."214~215در ابتدا به نظر می رسد کار بیشتر است. سپس به نوعی آرامش تبدیل می شود. تصمیمات مربوط به عملکرد دیگر در ترکیبی از پیش فرض ها، اکتشافی و حافظه قبیله ای پنهان نیستند. آنها در کد هستند.216~217## منابع مفید218~219- [یادداشت های انتشار Next.js 16](https://nextjs.org/blog/next-16)220- [اجزای کش - اسناد Next.js](https://nextjs.org/docs/app/getting-started/cache-components)221- [استفاده از کش - اسناد Next.js](https://nextjs.org/docs/app/api-reference/directives/use-cache)222- [React Compiler نسخه 1.0](https://react.dev/blog/2025/10/07/react-compiler-1)223~
NORMAL · nextjs-16-cache-components.md [readonly]223 lines · :q to close