spinny:~/writing $ vim nextjs-16-cache-components.md
1~2Een van de meest vervelende vragen in Next.js is al jaren: "Is deze pagina statisch of dynamisch?". Het lijkt een simpele vraag, totdat je een aanroep toevoegt aan `cookies()`, een `fetch` met verschillende opties, een databaseclient, een CMS, een winkelwagentje of een stukje aangepaste inhoud.3~4Next.js 16 is interessant omdat het dit gesprek minder mysterieus probeert te maken. Het elimineert de complexiteit niet, maar het verschuift het mentale model: routes zijn standaard dynamisch, de cache declareert zichzelf waar nodig, en `Suspense` wordt de natuurlijke manier om snelle shells samen te stellen met onderdelen die actueel blijven.5~6De functie die u moet begrijpen, is Cache Components. Stabiele Turbopack, React Compiler, `proxy.ts` en de nieuwe validerings-API's zijn belangrijk, maar ze draaien om hetzelfde probleem: snelle apps bouwen zonder te hoeven raden wat het raamwerk achter de schermen besliste.7~8## Omdat dit ding ertoe doet9~10In een echte app heb je niet alleen ‘statische pagina’s’ en ‘dynamische pagina’s’. Je hebt verschillende stukken met verschillende behoeften.11~12Het productblad kan enkele keren per dag veranderen. De prijs kan vaker veranderen. Beschikbaarheid moet bijna live zijn. De gebruikersnaam is persoonlijk. Recensies kunnen worden gestreamd. De zijbalk kan stabiel zijn. De kar niet.13~14Als je alles als één geheel beschouwt, kom je altijd terecht in een van de twee uitersten:15~16- agressieve caching en risico op het zien van oude gegevens;17- overal dynamische weergave en prestaties slechter dan nodig.18~19Cache Components dient juist om deze valse keuze te voorkomen.20~21## Het model in de praktijk22~23Met `cacheComponents: true` kun je aangeven wat cachebaar is met `"use cache"`. Vervolgens kunt u de duur en tags koppelen aan `cacheLife()` en `cacheTag()`. Dynamische delen blijven dynamisch en kunnen worden geïsoleerd met `Suspense`.24~25```mermaid26flowchart TD27 Request[Gebruikersverzoek] --> Shell[Gecachte schaal]28 Request --> Dynamic[Dynamische secties]29 Shell --> FirstPaint[Eerste snelle inhoud]30 Dynamic --> Stream[Streamen binnen Suspense]31 Stream --> Complete[Volledige pagina]32```33~34De opstelling is klein:35~36```typescript37// next.config.ts38import type { NextConfig } from 'next';39~40const nextConfig: NextConfig = {41 cacheComponents: true,42};43~44export default nextConfig;45```46~47De grote verandering zit niet in de configuratie. Het zit in de manier waarop u begint met het schrijven van de componenten.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~93De pagina hoeft niet volledig in de cache of dynamisch te zijn. Het productblad kan snel en herbruikbaar zijn. Voorraad kan vers blijven. De gebruiker ziet meteen iets, zonder te wachten op het langzaamste deel.94~95## `use cache` is uitvoerbare documentatie96~97Wat ik leuk vind aan `"use cache"` is dat het je dwingt een intentie expliciet te maken. Als je een functie leest, begrijp je meteen dat iemand heeft besloten: “deze gegevens kunnen worden hergebruikt”.98~99Het is vooral handig als u `fetch` niet gebruikt. Veel apps lezen gegevens van Prisma, Drizzle, interne SDK's, CMS-clients of servicefuncties. In die gevallen was de oude redenering, die alleen op `fetch`-opties was gebaseerd, niet voldoende.100~101Een vuistregel:102~103- cachea-inhoud relatief stabiel;104- gebruik gedetailleerde tags;105- laat dynamische machtigingen, sessies, winkelwagentjes, meldingen en transactiestatussen achter;106- plaats langzame delen in `Suspense`;107- meet voordat u zegt: "we hebben de prestaties verbeterd".108~109## Maak het ongeldig zonder alles weg te gooien110~111De cache is alleen nuttig als u deze nauwkeurig kunt bijwerken. Hier worden `cacheTag`, `revalidateTag` en `updateTag` belangrijk.112~113Voorbeeld: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~130Het belangrijke detail is het label. `product:${productId}` geeft een precieze grens aan. `products` vertelt een enorme emmer. In eerste instantie is de enorme emmer comfortabel; na een paar maanden wordt het de reden dat je een halve app ongeldig maakt om een titel te wijzigen.131~132## Stabiele Turbopack: het deel dat je elke dag hoort133~134Next.js 16 brengt Turbopack naar het centrum voor ontwikkeling en bouw. Het is niet de meest poëtische functie, maar wel degene die je voelt terwijl je werkt: een server die eerder start, een snellere verversing, builds die niet meer aanvoelen als een gedwongen koffiepauze.135~136Dat gezegd hebbende, zou ik een codebase vol aangepaste plug-ins niet met mijn ogen dicht migreren. Ik zou controleren:137~138- lokale bouw;139- niet-standaard import;140- MDX, SVG en CSS;141- Webpack-plug-ins over;142- kritische pagina's;143- verschillen in bouwtijden.144~145Voor nieuwe projecten zou ik uitgaan van de standaard. Voor volwassen zou ik een afgemeten migratie uitvoeren.146~147## React Compiler: verwijder ruis, niet gedachte148~149React Compiler 1.0 is stabiel en Next.js 16 ondersteunt het met `reactCompiler`. De belofte is om veel handmatig onthouden te verminderen: minder `memo`, minder `useMemo`, minder `useCallback` gebruikt "voor de veiligheid".150~151```typescript152// next.config.ts153import type { NextConfig } from 'next';154~155const nextConfig: NextConfig = {156 reactCompiler: true,157};158~159export default nextConfig;160```161~162Ik zou het niet als magisch stof behandelen. De compiler helpt als de code de React-regels goed volgt. Als componenten vreemde bijwerkingen, verborgen mutaties of slecht gebruikte hooks hebben, moet dat eerst worden opgelost.163~164De gezonde manier om het te proberen:165~1661. update `eslint-plugin-react-hooks`;1672. feitelijke overtredingen oplossen;1683. schakel het in op een gecontroleerd gebied;1694. meet bouwtijd en gedrag;1705. verwijder handmatige memo's alleen als deze niet langer nodig zijn.171~172Het doel is niet om elke `useMemo` te wissen. Het doel is om te stoppen met het schrijven van preventieve memo's, omdat we bang zijn voor weergave.173~174## `proxy.ts` en de netwerkgrens175~176De oude `middleware.ts` wordt `proxy.ts`. Het is een naamswijziging, maar het is logisch: dat bestand bevindt zich op de verzoekgrens en is geen traditionele generieke middleware in backend-stijl.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~193De regel hier is simpel: houd het klein. Omleiding, auth-routing, headers, essentiële herschrijvingen. Als het begint te voelen als een tweede backend, doet het waarschijnlijk te veel.194~195## Hoe ik echt zou migreren196~197Ik zou niet alle functies tegelijk inschakelen. Ik zou dit doen:198~1991. Ik update Next, React en React DOM;2002. Ik start de officiële codemod;2013. Ik repareer de belangrijkste wijzigingen in `params`, `searchParams`, `cookies()`, `headers()` en `draftMode()`;2024. Ik migreer `middleware.ts` naar `proxy.ts`;2035. Ik controleer builds en kritische pagina's;2046. Ik schakel Cache Components in op een sectie waar de cache momenteel voor wrijving zorgt;2057. Ik definieer conventies voor tags en ongeldigverklaring;2068. Ik probeer React Compiler afzonderlijk;2079. vergelijking van statistieken voor en na.208~209De goede migratie is niet degene die alle nieuwe functies gebruikt. Het maakt het gedrag van de app leesbaarder.210~211## Wat verandert er in de manier van denken212~213Het handigste aan Next.js 16 is dat het je dwingt om intenties beter te benoemen. Een functie is niet alleen maar "haal het product uit de database". Het is "haal het product, ik kan het urenlang in de cache bewaren, ik maak het ongeldig met deze tag". Een component is niet alleen maar "geef de pagina weer". Het is "dit is de snelle shell, dit stuk is persoonlijk, dit komt streaming."214~215In eerste instantie lijkt het meer werk. Dan wordt het een vorm van kalmte. Prestatiebeslissingen zijn niet langer verborgen in een combinatie van standaardwaarden, heuristieken en tribaal geheugen. Ze staan in de code.216~217## Nuttige bronnen218~219- [Next.js 16 release-opmerkingen](https://nextjs.org/blog/next-16)220- [Cachecomponenten - Next.js-documenten](https://nextjs.org/docs/app/getting-started/cache-components)221- [gebruik cache - Next.js-documenten](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