NAME
nextjs-16-cache-components — Next.js 16, Cache Components og React Compiler: hvad der virkelig ændrer sig
SYNOPSIS
cat nextjs-16-cache-components.md
DESCRIPTION
I årevis har et af de mest irriterende spørgsmål i Next.js været: "Er denne side statisk eller dynamisk?". Det virker som et simpelt spørgsmål, indtil du tilføjer et opkald til cookies(), en fetch med forskellige muligheder, en databaseklient, et CMS, en indkøbskurv eller et stykke tilpasset indhold.
Next.js 16 er interessant, fordi den forsøger at gøre denne samtale mindre mystisk. Det eliminerer ikke kompleksitet, men det flytter den mentale model: ruter er dynamiske som standard, cachen erklærer sig selv, hvor det er nødvendigt, og Suspense bliver den naturlige måde at komponere hurtige skaller med dele, der forbliver friske.
Funktionen, der skal forstås, er Cache-komponenter. Stabil Turbopack, React Compiler, proxy.ts og de nye invaliderings-API'er er vigtige, men de kredser om det samme problem: at bygge hurtige apps uden at skulle gætte, hvad rammerne besluttede bag kulisserne.
Fordi denne ting betyder noget
I en rigtig app har du ikke bare "statiske sider" og "dynamiske sider". Du har forskellige stykker med forskellige behov.
Produktarket kan ændres et par gange om dagen. Prisen kan ændre sig oftere. Tilgængeligheden skal være næsten live. Brugernavnet er personligt. Anmeldelser kan streames. Sidebjælken kan være stabil. Det gør vognen ikke.
Hvis du behandler alt som én enhed, ender du altid i en af to yderpunkter:
- aggressiv caching og risiko for at se gamle data;
- dynamisk gengivelse overalt og ydeevne dårligere end nødvendigt.
Cache-komponenter tjener netop til at undgå dette falske valg.
Modellen i praksis
Med cacheComponents: true kan du erklære, hvad der kan cachelagres ved hjælp af "use cache". Derefter kan du knytte varighed og tags til cacheLife() og cacheTag(). Dynamiske dele forbliver dynamiske og kan isoleres med Suspense.
Opsætningen er lille:
// next.config.ts import type { NextConfig } from 'next'; const nextConfig: NextConfig = { cacheComponents: true, }; export default nextConfig;
Den store ændring er ikke i konfigurationen. Det er i, hvordan du begynder at skrive komponenterne.
// 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> </> ); }
Siden behøver ikke at være helt i cache eller være dynamisk. Produktarket kan være hurtigt og genanvendeligt. Beholdningen kan forblive frisk. Brugeren ser noget med det samme, uden at vente på den langsomste del.
use cache er eksekverbar dokumentation
Det, jeg godt kan lide ved "use cache", er, at det tvinger dig til at udtrykke en intention. Når du læser en funktion, forstår du med det samme, at nogen har besluttet: "disse data kan genbruges".
Det er især nyttigt, når du ikke bruger fetch. Mange apps læser data fra Prisma, Drizzle, interne SDK'er, CMS-klienter eller servicefunktioner. I disse tilfælde var den gamle begrundelse kun baseret på fetch muligheder ikke nok.
En tommelfingerregel:
- cacheindhold relativt stabilt;
- brug granulære tags;
- efterlader dynamiske tilladelser, sessioner, vogne, meddelelser og transaktionstilstande;
- sæt langsomme dele i
Suspense; - måle før du siger "vi forbedrede ydeevnen".
Ugyldig uden at smide alt væk
Cachen er kun nyttig, hvis du kan opdatere den nøjagtigt. Her bliver cacheTag, revalidateTag og updateTag vigtige.
Eksempel:
'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}`); }
Den vigtige detalje er mærket. product:${productId} fortæller en præcis grænse. products fortæller en kæmpe spand. Først er den enorme spand behagelig; efter et par måneder bliver det grunden til, at du ugyldiggør en halv app for at ændre en titel.
Stabil Turbopack: den del, du hører hver dag
Next.js 16 bringer Turbopack til centrum for udvikling og opbygning. Det er ikke det mest poetiske træk, men det er det, du føler, mens du arbejder: server, der starter tidligere, hurtigere opdatering, opbygninger, der holder op med at føles som en tvungen kaffepause.
Når det er sagt, ville jeg ikke migrere en kodebase fuld af brugerdefinerede plugins med lukkede øjne. Jeg ville tjekke:
- lokal opbygning;
- ikke-standard import;
- MDX, SVG og CSS;
- Webpack plugins tilbage;
- kritiske sider;
- forskelle i byggetider.
For nye projekter ville jeg starte fra standard. For modne mennesker ville jeg lave en afmålt migration.
React Compiler: fjern støj, ikke tænkt
React Compiler 1.0 er stabil og Next.js 16 understøtter den med reactCompiler. Løftet er at reducere en masse manuel memoisering: mindre memo, mindre useMemo, mindre useCallback brugt "for sikkerheden".
// next.config.ts import type { NextConfig } from 'next'; const nextConfig: NextConfig = { reactCompiler: true, }; export default nextConfig;
Jeg ville ikke behandle det som et magisk støv. Compileren hjælper, når koden følger React-reglerne godt. Hvis komponenter har mærkelige bivirkninger, skjulte mutationer eller dårligt brugte kroge, skal det rettes først.
Den sunde måde at prøve det på:
- opdatering
eslint-plugin-react-hooks; - rette faktiske overtrædelser;
- aktivere det på et kontrolleret område;
- måle byggetid og adfærd;
- fjern kun manuel huskeseddel, når det ikke længere er nødvendigt.
Målet er ikke at slette hver useMemo. Målet er at stoppe med at skrive forebyggende huskeseddel, fordi vi er bange for at gengive.
proxy.ts og netværksgrænsen
Den gamle middleware.ts bliver proxy.ts. Det er en navneændring, men det giver mening: den fil sidder ved anmodningsgrænsen, det er ikke traditionel backend-stil generisk middleware.
// 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(); }
Reglen her er enkel: hold den lille. Omdirigering, godkendelsesrouting, overskrifter, væsentlige omskrivninger. Hvis det begynder at føles som en anden backend, gør det sandsynligvis for meget.
Hvordan jeg virkelig ville migrere
Jeg ville ikke slå alle funktionerne til på én gang. Jeg ville gøre dette:
- Jeg opdaterer Next, React og React DOM;
- Jeg starter den officielle kodemod;
- Jeg retter brydende ændringer på
params,searchParams,cookies(),headers()ogdraftMode(); - Jeg migrerer
middleware.tstilproxy.ts; - Jeg tjekker builds og kritiske sider;
- Jeg aktiverer Cache-komponenter på en sektion, hvor cachen i øjeblikket skaber friktion;
- Jeg definerer konventioner for tags og invalidering;
- Jeg prøver React Compiler separat;
- sammenligning af målinger før og efter.
Den gode migration er ikke den, der bruger alle de nye funktioner. Det er det, der gør appens adfærd mere læsbar.
Hvad ændrer måden at tænke på
Det mest nyttige ved Next.js 16 er, at det tvinger dig til at nævne intentioner bedre. En funktion er ikke bare "hent produktet fra databasen". Det er "få produktet, jeg kan cache det i timevis, jeg gør det ugyldigt med dette tag". En komponent er ikke bare "render siden". Det er "dette er den hurtige skal, dette stykke er personligt, det kommer streaming."
Umiddelbart virker det som mere arbejde. Så bliver det en form for ro. Ydeevnebeslutninger er ikke længere skjult i en kombination af standardindstillinger, heuristik og stammehukommelse. De er i koden.
Nyttige kilder
METADATA
- date: 2026-05-24
- reading: 6 min
- author: Filippo Spinella
- tags: Next.js, React, Frontend, Performance