spinny:~/writing $ less nextjs-16-cache-components.md
12Een 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.34Next.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.56De 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.78## Omdat dit ding ertoe doet910In een echte app heb je niet alleen ‘statische pagina’s’ en ‘dynamische pagina’s’. Je hebt verschillende stukken met verschillende behoeften.1112Het 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.1314Als je alles als één geheel beschouwt, kom je altijd terecht in een van de twee uitersten:1516- agressieve caching en risico op het zien van oude gegevens;17- overal dynamische weergave en prestaties slechter dan nodig.1819Cache Components dient juist om deze valse keuze te voorkomen.2021## Het model in de praktijk2223Met `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`.2425```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```3334De opstelling is klein:3536```typescript37// next.config.ts38import type { NextConfig } from 'next';3940const nextConfig: NextConfig = {41 cacheComponents: true,42};4344export default nextConfig;45```4647De grote verandering zit niet in de configuratie. Het zit in de manier waarop u begint met het schrijven van de componenten.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```9293De 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.9495## `use cache` is uitvoerbare documentatie9697Wat 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”.9899Het 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.100101Een vuistregel:102103- 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".108109## Maak het ongeldig zonder alles weg te gooien110111De cache is alleen nuttig als u deze nauwkeurig kunt bijwerken. Hier worden `cacheTag`, `revalidateTag` en `updateTag` belangrijk.112113Voorbeeld: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```129130Het 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.131132## Stabiele Turbopack: het deel dat je elke dag hoort133134Next.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.135136Dat gezegd hebbende, zou ik een codebase vol aangepaste plug-ins niet met mijn ogen dicht migreren. Ik zou controleren:137138- lokale bouw;139- niet-standaard import;140- MDX, SVG en CSS;141- Webpack-plug-ins over;142- kritische pagina's;143- verschillen in bouwtijden.144145Voor nieuwe projecten zou ik uitgaan van de standaard. Voor volwassen zou ik een afgemeten migratie uitvoeren.146147## React Compiler: verwijder ruis, niet gedachte148149React 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".150151```typescript152// next.config.ts153import type { NextConfig } from 'next';154155const nextConfig: NextConfig = {156 reactCompiler: true,157};158159export default nextConfig;160```161162Ik 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.163164De gezonde manier om het te proberen:1651661. 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.171172Het 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.173174## `proxy.ts` en de netwerkgrens175176De 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.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```192193De 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.194195## Hoe ik echt zou migreren196197Ik zou niet alle functies tegelijk inschakelen. Ik zou dit doen:1981991. 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.208209De goede migratie is niet degene die alle nieuwe functies gebruikt. Het maakt het gedrag van de app leesbaarder.210211## Wat verandert er in de manier van denken212213Het 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."214215In 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.216217## Nuttige bronnen218219- [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
:Next.js 16, Cache Components en React Compiler: wat er echt verandertlines 1-223 (END) — press q to close