spinny:~/writing $ less nextjs-16-cache-components.md
12برای سالها یکی از آزاردهندهترین سوالات در Next.js این بود: "این صفحه ثابت است یا پویا؟". این یک سوال ساده به نظر می رسد، تا زمانی که یک تماس به `cookies()`، یک `fetch` با گزینه های مختلف، یک سرویس گیرنده پایگاه داده، یک CMS، یک سبد خرید، یا یک قطعه از محتوای سفارشی اضافه کنید.34Next.js 16 جالب است زیرا سعی می کند این مکالمه را کمتر مرموز کند. این پیچیدگی را از بین نمیبرد، اما مدل ذهنی را تغییر میدهد: مسیرها بهطور پیشفرض پویا هستند، حافظه پنهان در جایی که لازم است خود را اعلام میکند، و `Suspense` راهی طبیعی برای ترکیب پوستههای سریع با قطعاتی میشود که تازه میمانند.56ویژگی قابل درک، Cache Components است. Stable Turbopack، React Compiler، `proxy.ts`، و API های جدید باطل اهمیت دارند، اما حول همین مشکل می چرخند: ساخت برنامه های سریع بدون نیاز به حدس زدن چارچوب در پشت صحنه چه تصمیمی گرفته است.78## چون این چیز مهمه910در یک برنامه واقعی، شما فقط "صفحات ثابت" و "صفحات پویا" ندارید. شما قطعات مختلف با نیازهای متفاوت دارید.1112برگه محصول ممکن است چند بار در روز تغییر کند. قیمت ممکن است بیشتر تغییر کند. در دسترس بودن باید تقریباً زنده باشد. نام کاربری شخصی است. نظرات را می توان به صورت جریانی پخش کرد. نوار کناری می تواند پایدار باشد. سبد خرید ندارد.1314اگر همه چیز را به عنوان یک واحد در نظر بگیرید، همیشه در یکی از دو حالت افراطی قرار می گیرید:1516- حافظه پنهان تهاجمی و خطر دیدن داده های قدیمی؛17- رندر پویا در همه جا و عملکرد بدتر از حد لازم.1819Cache Components دقیقاً برای جلوگیری از این انتخاب اشتباه عمل می کند.2021## مدل در عمل2223با `cacheComponents: true`، می توانید با استفاده از `"use cache"` آنچه را که در حافظه پنهان است، اعلام کنید. سپس می توانید مدت زمان و برچسب ها را با `cacheLife()` و `cacheTag()` مرتبط کنید. قطعات دینامیک پویا باقی می مانند و با `Suspense` قابل جداسازی هستند.2425```mermaid26flowchart TD27 Request[درخواست کاربر] --> Shell[پوسته ذخیره شده]28 Request --> Dynamic[مقاطع پویا]29 Shell --> FirstPaint[اولین محتوای سریع]30 Dynamic --> Stream[در حال پخش در داخل Suspense]31 Stream --> Complete[صفحه کامل]32```3334تنظیمات کوچک است:3536```typescript37// next.config.ts38import type { NextConfig } from 'next';3940const nextConfig: NextConfig = {41 cacheComponents: true,42};4344export default nextConfig;45```4647تغییر بزرگ در پیکربندی نیست. این در نحوه شروع نوشتن اجزاست.4849```tsx50// app/products/[slug]/page.tsx51import { Suspense } from 'react';52import { cacheLife, cacheTag } from 'next/cache';5354async function getProduct(slug: string) {55 'use cache';5657 cacheLife('hours');58 cacheTag(`product:${slug}`);5960 return db.product.findUnique({ where: { slug } });61}6263async function ProductDetails({ slug }: { slug: string }) {64 const product = await getProduct(slug);6566 return (67 <section>68 <h1>{product.name}</h1>69 <p>{product.description}</p>70 </section>71 );72}7374async function LiveInventory({ slug }: { slug: string }) {75 const inventory = await db.inventory.findFirst({ where: { slug } });76 return <p>{inventory.quantity} pezzi disponibili</p>;77}7879export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {80 const { slug } = await params;8182 return (83 <>84 <ProductDetails slug={slug} />85 <Suspense fallback={<p>Controllo disponibilità...</p>}>86 <LiveInventory slug={slug} />87 </Suspense>88 </>89 );90}91```9293لازم نیست صفحه تماماً کش یا تماماً پویا باشد. برگه محصول می تواند سریع و قابل استفاده مجدد باشد. موجودی می تواند تازه بماند. کاربر بلافاصله چیزی را می بیند، بدون اینکه منتظر کندترین قسمت باشد.9495## `use cache` مستندات اجرایی است9697چیزی که من در مورد `"use cache"` دوست دارم این است که شما را مجبور می کند که قصدی را صریح بیان کنید. هنگامی که یک تابع را می خوانید، بلافاصله متوجه می شوید که شخصی تصمیم گرفته است: "این داده ها قابل استفاده مجدد هستند".9899به خصوص زمانی که از `fetch` استفاده نمی کنید مفید است. بسیاری از برنامه ها داده های Prisma، Drizzle، SDK های داخلی، کلاینت های CMS یا توابع سرویس را می خوانند. در آن موارد، استدلال قدیمی فقط بر اساس گزینه های `fetch` کافی نبود.100101یک قانون سرانگشتی:102103- محتوای cachea نسبتاً پایدار است.104- از برچسب های دانه ای استفاده کنید.105- مجوزهای پویا، جلسات، سبد خریدها، اعلانها و وضعیتهای تراکنش را ترک میکند.106- قطعات کند را داخل `Suspense` قرار دهید.107- قبل از گفتن "ما عملکرد را بهبود بخشیم" اندازه گیری کنید.108109## بدون دور ریختن همه چیز باطل کنید110111کش تنها زمانی مفید است که بتوانید آن را به طور دقیق به روز کنید. در اینجا `cacheTag`، `revalidateTag` و `updateTag` مهم می شوند.112113مثال:114115```typescript116'use server';117118import { updateTag } from 'next/cache';119120export async function updateProductName(productId: string, name: string) {121 await db.product.update({122 where: { id: productId },123 data: { name },124 });125126 updateTag(`product:${productId}`);127}128```129130جزئیات مهم برچسب است. `product:${productId}` یک مرز دقیق را نشان می دهد. `products` به یک سطل بزرگ می گوید. در ابتدا سطل بزرگ راحت است. بعد از چند ماه این دلیلی می شود که نیمی از یک برنامه را برای تغییر عنوان باطل کنید.131132## توربوپک پایدار: بخشی که هر روز می شنوید133134Next.js 16 Turbopack را برای توسعه و ساخت به مرکز می آورد. این شاعرانهترین ویژگی نیست، اما آن چیزی است که در حین کار احساس میکنید: سروری که زودتر شروع به کار میکند، سریعتر بهروزرسانی میشود، ساختهایی که احساس یک استراحت اجباری قهوه را ندارند.135136با این حال، من یک پایگاه کد پر از پلاگین های سفارشی را با چشمان بسته منتقل نمی کنم. من بررسی می کنم:137138- ساخت محلی؛139- واردات غیر استاندارد؛140- MDX، SVG و CSS؛141- افزونه های Webpack باقی مانده است.142- صفحات انتقادی؛143- تفاوت در زمان ساخت144145برای پروژه های جدید، از حالت پیش فرض شروع می کنم. برای افراد بالغ، من یک مهاجرت سنجیده انجام می دهم.146147## React Compiler: حذف نویز، نه فکر148149React Compiler 1.0 پایدار است و Next.js 16 آن را با `reactCompiler` پشتیبانی می کند. وعده کاهش مقدار زیادی از یادداشت دستی است: کمتر `memo`، کمتر `useMemo`، کمتر `useCallback` استفاده شده "برای ایمنی".150151```typescript152// next.config.ts153import type { NextConfig } from 'next';154155const nextConfig: NextConfig = {156 reactCompiler: true,157};158159export default nextConfig;160```161162من با آن مانند یک گرد و غبار جادویی رفتار نمی کنم. کامپایلر زمانی کمک می کند که کد به خوبی از قوانین React پیروی کند. اگر اجزاء دارای عوارض جانبی عجیب، جهش های پنهان یا قلاب های بد استفاده شده باشند، ابتدا باید اصلاح شوند.163164روش سالم امتحان کردن:1651661. به روز رسانی `eslint-plugin-react-hooks`؛1672. رفع تخلفات واقعی؛1683. آن را در یک منطقه کنترل شده فعال کنید.1694. اندازه گیری زمان ساخت و رفتار.1705. ذخیره سازی دستی را فقط زمانی حذف کنید که دیگر مورد نیاز نباشد.171172هدف پاک کردن هر `useMemo` نیست. هدف این است که نوشتن یادداشت پیشگیرانه را متوقف کنیم زیرا از رندر می ترسیم.173174## `proxy.ts` و مرز شبکه175176`middleware.ts` قدیمی به `proxy.ts` تبدیل می شود. این یک تغییر نام است، اما منطقی است: آن فایل در مرز درخواست قرار میگیرد، یک میانافزار عمومی سنتی به سبک باطن نیست.177178```typescript179// proxy.ts180import { NextRequest, NextResponse } from 'next/server';181182export default function proxy(request: NextRequest) {183 const isLoggedIn = Boolean(request.cookies.get('session'));184185 if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {186 return NextResponse.redirect(new URL('/login', request.url));187 }188189 return NextResponse.next();190}191```192193قانون اینجا ساده است: آن را کوچک نگه دارید. تغییر مسیر، مسیریابی احراز هویت، هدرها، بازنویسی های ضروری. اگر شروع به احساس یک باطن دوم کند، احتمالاً کار زیادی انجام می دهد.194195## واقعا چقدر مهاجرت میکردم196197من همه ویژگی ها را به یکباره روشن نمی کنم. من این کار را انجام می دهم:1981991. من 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. مقایسه معیارهای قبل و بعد208209مهاجرت خوب آن چیزی نیست که از همه ویژگی های جدید استفاده کند. این چیزی است که رفتار برنامه را خواناتر می کند.210211## آنچه در طرز فکر تغییر می کند212213مفیدترین چیز در مورد Next.js 16 این است که شما را مجبور می کند تا اهداف را بهتر نامگذاری کنید. یک تابع فقط "دریافت محصول از پایگاه داده" نیست. این "محصول را دریافت کنید، می توانم آن را برای ساعت ها کش کنم، با این برچسب آن را باطل می کنم". کامپوننت فقط "رندر صفحه" نیست. این "این پوسته سریع است، این قطعه شخصی است، این جریان پخش می شود."214215در ابتدا به نظر می رسد کار بیشتر است. سپس به نوعی آرامش تبدیل می شود. تصمیمات مربوط به عملکرد دیگر در ترکیبی از پیش فرض ها، اکتشافی و حافظه قبیله ای پنهان نیستند. آنها در کد هستند.216217## منابع مفید218219- [یادداشت های انتشار 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
:Next.js 16، Cache Components و React Compiler: آنچه واقعاً تغییر می کندlines 1-223 (END) — press q to close