spinny:~/writing $ vim nextjs-16-cache-components.md
1~2Selama bertahun-tahun, salah satu soalan yang paling menjengkelkan dalam Next.js ialah: "Adakah halaman ini statik atau dinamik?". Nampaknya seperti soalan mudah, sehingga anda menambah panggilan ke `cookies()`, `fetch` dengan pilihan yang berbeza, pelanggan pangkalan data, CMS, troli beli-belah atau sekeping kandungan tersuai.3~4Seterusnya.js 16 menarik kerana ia cuba menjadikan perbualan ini kurang misteri. Ia tidak menghapuskan kerumitan, tetapi ia mengubah model mental: laluan adalah dinamik secara lalai, cache mengisytiharkan dirinya sendiri di mana diperlukan, dan `Suspense` menjadi cara semula jadi untuk mengarang cengkerang pantas dengan bahagian yang kekal segar.5~6Ciri yang perlu difahami ialah Komponen Cache. Turbopack Stabil, React Compiler, `proxy.ts` dan API pembatalan baharu adalah penting, tetapi ia berkisar pada masalah yang sama: membina apl pantas tanpa perlu meneka apa yang diputuskan oleh rangka kerja di sebalik tabir.7~8## Kerana perkara ini penting9~10Dalam apl sebenar, anda bukan sahaja mempunyai "halaman statik" dan "halaman dinamik". Anda mempunyai kepingan yang berbeza dengan keperluan yang berbeza.11~12Helaian produk mungkin berubah beberapa kali sehari. Harga mungkin berubah lebih kerap. Ketersediaan mesti hampir langsung. Nama pengguna adalah peribadi. Ulasan boleh distrim. Bar sisi boleh menjadi stabil. Troli tidak.13~14Jika anda menganggap segala-galanya sebagai satu unit, anda sentiasa berada dalam salah satu daripada dua keterlaluan:15~16- caching agresif dan risiko melihat data lama;17- pemaparan dinamik di mana-mana dan prestasi lebih teruk daripada yang diperlukan.18~19Komponen Cache berfungsi dengan tepat untuk mengelakkan pilihan palsu ini.20~21## Model dalam amalan22~23Dengan `cacheComponents: true`, anda boleh mengisytiharkan perkara yang boleh dicache menggunakan `"use cache"`. Kemudian anda boleh mengaitkan tempoh dan teg dengan `cacheLife()` dan `cacheTag()`. Bahagian dinamik kekal dinamik dan boleh diasingkan dengan `Suspense`.24~25```mermaid26flowchart TD27 Request[Permintaan pengguna] --> Shell[Cache shell]28 Request --> Dynamic[Bahagian dinamik]29 Shell --> FirstPaint[Kandungan cepat pertama]30 Dynamic --> Stream[Menstrim dalam Suspense]31 Stream --> Complete[Halaman penuh]32```33~34Persediaan adalah kecil:35~36```typescript37// next.config.ts38import type { NextConfig } from 'next';39~40const nextConfig: NextConfig = {41 cacheComponents: true,42};43~44export default nextConfig;45```46~47Perubahan besar tiada dalam konfigurasi. Ia terletak pada cara anda mula menulis komponen.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~93Halaman tidak perlu semuanya dicache atau semua dinamik. Lembaran produk boleh cepat dan boleh digunakan semula. Inventori boleh kekal segar. Pengguna melihat sesuatu dengan segera, tanpa menunggu bahagian yang paling perlahan.94~95## `use cache` ialah dokumentasi boleh laku96~97Perkara yang saya suka tentang `"use cache"` ialah ia memaksa anda untuk menyatakan niat yang jelas. Apabila anda membaca fungsi, anda segera memahami bahawa seseorang telah memutuskan: "data ini boleh digunakan semula".98~99Ia amat berguna apabila anda tidak menggunakan `fetch`. Banyak apl membaca data daripada Prisma, Drizzle, SDK dalaman, pelanggan CMS atau fungsi perkhidmatan. Dalam kes tersebut, alasan lama hanya berdasarkan pilihan `fetch` tidak mencukupi.100~101Peraturan biasa:102~103- kandungan cachea agak stabil;104- gunakan tag berbutir;105- meninggalkan kebenaran dinamik, sesi, troli, pemberitahuan dan keadaan transaksi;106- letak bahagian perlahan di dalam `Suspense`;107- ukur sebelum berkata "kami meningkatkan prestasi".108~109## Batal tanpa membuang segala-galanya110~111Cache hanya berguna jika anda boleh mengemas kininya dengan tepat. Di sini `cacheTag`, `revalidateTag` dan `updateTag` menjadi penting.112~113Contoh: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~130Perincian penting ialah tag. `product:${productId}` memberitahu sempadan yang tepat. `products` memberitahu baldi besar. Pada mulanya baldi besar itu selesa; selepas beberapa bulan ia menjadi sebab anda membatalkan separuh apl untuk menukar tajuk.131~132## Turbopack Stabil: bahagian yang anda dengar setiap hari133~134Next.js 16 membawa Turbopack ke pusat untuk pembangunan dan pembinaan. Ia bukan ciri yang paling puitis, tetapi ia adalah ciri yang anda rasa semasa anda bekerja: pelayan yang bermula lebih awal, menyegarkan lebih cepat, membina yang berhenti berasa seperti rehat kopi paksa.135~136Yang berkata, saya tidak akan memindahkan pangkalan kod yang penuh dengan pemalam tersuai dengan mata tertutup. Saya akan menyemak:137~138- binaan tempatan;139- modul bukan standard;140- MDX, SVG dan CSS;141- Pemalam Webpack ditinggalkan;142- halaman kritikal;143- perbezaan masa pembinaan.144~145Untuk projek baharu, saya akan bermula dari lalai. Bagi yang matang, saya akan melakukan penghijrahan terukur.146~147## React Compiler: keluarkan bunyi, bukan difikirkan148~149React Compiler 1.0 adalah stabil dan Next.js 16 menyokongnya dengan `reactCompiler`. Janji adalah untuk mengurangkan banyak hafalan manual: kurang `memo`, kurang `useMemo`, kurang `useCallback` digunakan "untuk keselamatan".150~151```typescript152// next.config.ts153import type { NextConfig } from 'next';154~155const nextConfig: NextConfig = {156 reactCompiler: true,157};158~159export default nextConfig;160```161~162Saya tidak akan menganggapnya seperti debu ajaib. Pengkompil membantu apabila kod mengikut peraturan React dengan baik. Jika komponen mempunyai kesan sampingan yang pelik, mutasi tersembunyi atau cangkuk yang tidak digunakan, ia perlu diperbaiki terlebih dahulu.163~164Cara sihat untuk mencubanya:165~1661. kemas kini `eslint-plugin-react-hooks`;1672. membetulkan pelanggaran sebenar;1683. membolehkannya di kawasan terkawal;1694. mengukur masa dan tingkah laku binaan;1705. alih keluar hafalan manual hanya apabila ia tidak lagi diperlukan.171~172Matlamatnya bukan untuk memadam setiap `useMemo`. Matlamatnya adalah untuk berhenti menulis hafalan pencegahan kerana kami takut untuk membuat.173~174## `proxy.ts` dan sempadan rangkaian175~176`middleware.ts` lama menjadi `proxy.ts`. Ia adalah perubahan nama, tetapi ia masuk akal: fail itu terletak pada sempadan permintaan, ia bukan perisian tengah generik gaya belakang tradisional.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~193Peraturan di sini adalah mudah: pastikan ia kecil. Ubah hala, penghalaan pengesahan, pengepala, penulisan semula penting. Jika ia mula terasa seperti bahagian belakang kedua, ia mungkin melakukan terlalu banyak.194~195## Bagaimana saya benar-benar akan berhijrah196~197Saya tidak akan menghidupkan semua ciri sekaligus. Saya akan melakukan ini:198~1991. Saya mengemas kini Seterusnya, React dan React DOM;2002. Saya melancarkan codemod rasmi;2013. Saya membetulkan perubahan yang rosak pada `params`, `searchParams`, `cookies()`, `headers()` dan `draftMode()`;2024. Saya berhijrah `middleware.ts` kepada `proxy.ts`;2035. Saya menyemak binaan dan halaman kritikal;2046. Saya mendayakan Komponen Cache pada bahagian di mana cache mencipta geseran pada masa ini;2057. Saya mentakrifkan konvensyen untuk teg dan pembatalan;2068. Saya cuba React Compiler secara berasingan;2079. perbandingan metrik sebelum dan selepas.208~209Penghijrahan yang baik bukanlah yang menggunakan semua ciri baharu. Ini yang menjadikan gelagat apl lebih mudah dibaca.210~211## Apakah perubahan dalam cara berfikir212~213Perkara yang paling berguna tentang Next.js 16 ialah ia memaksa anda untuk menamakan niat dengan lebih baik. Fungsi bukan sekadar "mendapatkan produk daripada pangkalan data". Ia adalah "dapatkan produk, saya boleh cache selama berjam-jam, saya membatalkannya dengan tag ini". Komponen bukan sekadar "memberi halaman". Ia adalah "ini adalah cengkerang cepat, bahagian ini adalah peribadi, ini datang secara penstriman."214~215Pada mulanya ia kelihatan seperti lebih banyak kerja. Kemudian ia menjadi satu bentuk ketenangan. Keputusan prestasi tidak lagi tersembunyi dalam gabungan lalai, heuristik dan ingatan puak. Mereka ada dalam kod.216~217## Sumber yang berguna218~219- [Nota keluaran Next.js 16](https://nextjs.org/blog/next-16)220- [Komponen Cache - Next.js docs](https://nextjs.org/docs/app/getting-started/cache-components)221- [gunakan cache - Next.js docs](https://nextjs.org/docs/app/api-reference/directives/use-cache)222- [React Compiler v1.0](https://react.dev/blog/2025/10/07/react-compiler-1)223~
NORMAL · nextjs-16-cache-components.md [readonly]223 lines · :q to close