Next.js 16, Komponen Cache dan React Compiler: apa yang sebenarnya berubah
· 6 min read · Filippo Spinella · Next.js, React, Frontend, Performance
Selama 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.
Seterusnya.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.
Ciri 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.
Kerana perkara ini penting
Dalam apl sebenar, anda bukan sahaja mempunyai "halaman statik" dan "halaman dinamik". Anda mempunyai kepingan yang berbeza dengan keperluan yang berbeza.
Helaian 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.
Jika anda menganggap segala-galanya sebagai satu unit, anda sentiasa berada dalam salah satu daripada dua keterlaluan:
- caching agresif dan risiko melihat data lama;
- pemaparan dinamik di mana-mana dan prestasi lebih teruk daripada yang diperlukan.
Komponen Cache berfungsi dengan tepat untuk mengelakkan pilihan palsu ini.
Model dalam amalan
Dengan 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.
Persediaan adalah kecil:
// next.config.ts import type { NextConfig } from 'next'; const nextConfig: NextConfig = { cacheComponents: true, }; export default nextConfig;
Perubahan besar tiada dalam konfigurasi. Ia terletak pada cara anda mula menulis komponen.
// app/products/[slug]/page.tsx import { Suspense } from 'react'; import { cacheLife, cacheTag } from 'next/cache'; async function getProduct(slug: string) { 'use cache'; cacheLife('hours'); cacheTag(`product:${slug}`); return db.product.findUnique({ where: { slug } }); } async function ProductDetails({ slug }: { slug: string }) { const product = await getProduct(slug); return ( <section> <h1>{product.name}</h1> <p>{product.description}</p> </section> ); } async function LiveInventory({ slug }: { slug: string }) { const inventory = await db.inventory.findFirst({ where: { slug } }); return <p>{inventory.quantity} pezzi disponibili</p>; } export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params; return ( <> <ProductDetails slug={slug} /> <Suspense fallback={<p>Controllo disponibilità...</p>}> <LiveInventory slug={slug} /> </Suspense> </> ); }
Halaman 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.
use cache ialah dokumentasi boleh laku
Perkara 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".
Ia 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.
Peraturan biasa:
- kandungan cachea agak stabil;
- gunakan tag berbutir;
- meninggalkan kebenaran dinamik, sesi, troli, pemberitahuan dan keadaan transaksi;
- letak bahagian perlahan di dalam
Suspense; - ukur sebelum berkata "kami meningkatkan prestasi".
Batal tanpa membuang segala-galanya
Cache hanya berguna jika anda boleh mengemas kininya dengan tepat. Di sini cacheTag, revalidateTag dan updateTag menjadi penting.
Contoh:
'use server'; import { updateTag } from 'next/cache'; export async function updateProductName(productId: string, name: string) { await db.product.update({ where: { id: productId }, data: { name }, }); updateTag(`product:${productId}`); }
Perincian 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.
Turbopack Stabil: bahagian yang anda dengar setiap hari
Next.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.
Yang berkata, saya tidak akan memindahkan pangkalan kod yang penuh dengan pemalam tersuai dengan mata tertutup. Saya akan menyemak:
- binaan tempatan;
- modul bukan standard;
- MDX, SVG dan CSS;
- Pemalam Webpack ditinggalkan;
- halaman kritikal;
- perbezaan masa pembinaan.
Untuk projek baharu, saya akan bermula dari lalai. Bagi yang matang, saya akan melakukan penghijrahan terukur.
React Compiler: keluarkan bunyi, bukan difikirkan
React 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".
// next.config.ts import type { NextConfig } from 'next'; const nextConfig: NextConfig = { reactCompiler: true, }; export default nextConfig;
Saya 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.
Cara sihat untuk mencubanya:
- kemas kini
eslint-plugin-react-hooks; - membetulkan pelanggaran sebenar;
- membolehkannya di kawasan terkawal;
- mengukur masa dan tingkah laku binaan;
- alih keluar hafalan manual hanya apabila ia tidak lagi diperlukan.
Matlamatnya bukan untuk memadam setiap useMemo. Matlamatnya adalah untuk berhenti menulis hafalan pencegahan kerana kami takut untuk membuat.
proxy.ts dan sempadan rangkaian
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.
// proxy.ts import { NextRequest, NextResponse } from 'next/server'; export default function proxy(request: NextRequest) { const isLoggedIn = Boolean(request.cookies.get('session')); if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) { return NextResponse.redirect(new URL('/login', request.url)); } return NextResponse.next(); }
Peraturan 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.
Bagaimana saya benar-benar akan berhijrah
Saya tidak akan menghidupkan semua ciri sekaligus. Saya akan melakukan ini:
- Saya mengemas kini Seterusnya, React dan React DOM;
- Saya melancarkan codemod rasmi;
- Saya membetulkan perubahan yang rosak pada
params,searchParams,cookies(),headers()dandraftMode(); - Saya berhijrah
middleware.tskepadaproxy.ts; - Saya menyemak binaan dan halaman kritikal;
- Saya mendayakan Komponen Cache pada bahagian di mana cache mencipta geseran pada masa ini;
- Saya mentakrifkan konvensyen untuk teg dan pembatalan;
- Saya cuba React Compiler secara berasingan;
- perbandingan metrik sebelum dan selepas.
Penghijrahan yang baik bukanlah yang menggunakan semua ciri baharu. Ini yang menjadikan gelagat apl lebih mudah dibaca.
Apakah perubahan dalam cara berfikir
Perkara 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."
Pada 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.