NAME
nextjs-16-cache-components — Next.js 16, Cache-komponenter och React Compiler: vad som verkligen förändras
SYNOPSIS
cat nextjs-16-cache-components.md
DESCRIPTION
I flera år har en av de mest irriterande frågorna i Next.js varit: "Är den här sidan statisk eller dynamisk?". Det verkar som en enkel fråga, tills du lägger till ett anrop till cookies(), en fetch med olika alternativ, en databasklient, ett CMS, en kundvagn eller ett stycke anpassat innehåll.
Next.js 16 är intressant eftersom det försöker göra den här konversationen mindre mystisk. Det eliminerar inte komplexitet, men det förändrar den mentala modellen: rutter är dynamiska som standard, cachen deklarerar sig själv där det behövs och Suspense blir det naturliga sättet att komponera snabba skal med delar som håller sig fräscha.
Funktionen att förstå är Cache-komponenter. Stabil Turbopack, React Compiler, proxy.ts och de nya invaliderings-API:erna är viktiga, men de kretsar kring samma problem: att bygga snabba appar utan att behöva gissa vad ramverket beslutade bakom kulisserna.
För det här spelar roll
I en riktig app har du inte bara "statiska sidor" och "dynamiska sidor". Du har olika pjäser med olika behov.
Produktbladet kan ändras några gånger om dagen. Priset kan ändras oftare. Tillgänglighet måste vara nästan live. Användarnamnet är personligt. Recensioner kan streamas. Sidofältet kan vara stabilt. Det gör inte vagnen.
Om du behandlar allt som en enhet hamnar du alltid i en av två ytterligheter:
- aggressiv cachning och risk för att se gamla data;
- dynamisk rendering överallt och prestanda sämre än nödvändigt.
Cache-komponenter tjänar just till att undvika detta felaktiga val.
Modellen i praktiken
Med cacheComponents: true kan du deklarera vad som är cachebart med "use cache". Sedan kan du associera varaktighet och taggar med cacheLife() och cacheTag(). Dynamiska delar förblir dynamiska och kan isoleras med Suspense.
Inställningen är liten:
// next.config.ts import type { NextConfig } from 'next'; const nextConfig: NextConfig = { cacheComponents: true, }; export default nextConfig;
Den stora förändringen finns inte i konfigurationen. Det är hur du börjar skriva komponenterna.
// 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> </> ); }
Sidan behöver inte vara helt cachad eller helt dynamisk. Produktbladet kan vara snabbt och återanvändbart. Inventeringen kan hålla sig fräsch. Användaren ser något direkt, utan att vänta på den långsammaste delen.
use cache är körbar dokumentation
Det jag gillar med "use cache" är att det tvingar dig att uttrycka en avsikt. När man läser en funktion förstår man direkt att någon har bestämt sig: "denna data kan återanvändas".
Det är särskilt användbart när du inte använder fetch. Många appar läser data från Prisma, Drizzle, interna SDK:er, CMS-klienter eller servicefunktioner. I dessa fall räckte inte det gamla resonemanget baserat på fetch-alternativ.
En tumregel:
- cacheinnehåll relativt stabilt;
- använd granulära taggar;
- lämnar dynamiska behörigheter, sessioner, vagnar, meddelanden och transaktionstillstånd;
- lägg långsamma delar inuti
Suspense; - mäta innan du säger "vi förbättrade prestandan".
Ogiltigförklara utan att kasta allt
Cachen är bara användbar om du kan uppdatera den korrekt. Här blir cacheTag, revalidateTag och updateTag viktiga.
Exempel:
'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 viktiga detaljen är taggen. product:${productId} visar en exakt gräns. products säger en stor hink. Till en början är den enorma skopan bekväm; efter några månader blir det anledningen till att du ogiltigförklarar en halv app för att ändra en titel.
Stabil Turbopack: delen du hör varje dag
Next.js 16 tar Turbopack till centrum för utveckling och konstruktion. Det är inte det mest poetiska inslaget, men det är den du känner medan du arbetar: server som startar tidigare, snabbare uppdatering, byggen som slutar kännas som en tvångsfika.
Som sagt, jag skulle inte migrera en kodbas full av anpassade plugins med slutna ögon. Jag skulle kolla:
- lokal byggnad;
- icke-standard import;
- MDX, SVG och CSS;
- Webpack plugins kvar;
- kritiska sidor;
- skillnader i byggtider.
För nya projekt skulle jag börja från standard. För mogna skulle jag göra en uppmätt migration.
React Compiler: ta bort brus, inte tänkt
React Compiler 1.0 är stabil och Next.js 16 stöder den med reactCompiler. Löftet är att minska mycket manuell memoisering: mindre memo, mindre useMemo, mindre useCallback används "för säkerhets skull".
// next.config.ts import type { NextConfig } from 'next'; const nextConfig: NextConfig = { reactCompiler: true, }; export default nextConfig;
Jag skulle inte behandla det som ett magiskt damm. Kompilatorn hjälper till när koden följer React-reglerna väl. Om komponenter har konstiga biverkningar, dolda mutationer eller dåligt använda krokar, måste det åtgärdas först.
Det hälsosamma sättet att prova det:
- uppdatera
eslint-plugin-react-hooks; - fixa faktiska överträdelser;
- aktivera det på ett kontrollerat område;
- mäta byggtid och beteende;
- ta bort manuell memoisering endast när den inte längre behövs.
Målet är inte att radera varje useMemo. Målet är att sluta skriva förebyggande memoisering eftersom vi är rädda för rendering.
proxy.ts och nätverksgränsen
Den gamla middleware.ts blir proxy.ts. Det är ett namnbyte, men det är vettigt: den filen ligger vid förfrågningsgränsen, det är inte traditionell mellanprogramvara i backend-stil.
// 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(); }
Regeln här är enkel: håll den liten. Omdirigering, autentiseringsdirigering, rubriker, viktiga omskrivningar. Om det börjar kännas som en andra backend, gör det förmodligen för mycket.
Hur jag verkligen skulle migrera
Jag skulle inte slå på alla funktioner på en gång. Jag skulle göra så här:
- Jag uppdaterar Next, React och React DOM;
- Jag startar den officiella codemoden;
- Jag fixar brytande ändringar på
params,searchParams,cookies(),headers()ochdraftMode(); - Jag migrerar
middleware.tstillproxy.ts; - Jag kollar builds och kritiska sidor;
- Jag aktiverar Cache-komponenter på en sektion där cachen för närvarande skapar friktion;
- Jag definierar konventioner för taggar och ogiltigförklaring;
- Jag försöker React Compiler separat;
- jämförelse av mätvärden före och efter.
Den goda migrationen är inte den som använder alla nya funktioner. Det är det som gör appens beteende mer läsbart.
Vad förändras i sättet att tänka
Det mest användbara med Next.js 16 är att det tvingar dig att namnge avsikter bättre. En funktion är inte bara "hämta produkten från databasen". Det är "skaffa produkten, jag kan cache den i timmar, jag ogiltigförklarar den med den här taggen". En komponent är inte bara "rendera sidan". Det är "det här är det snabba skalet, det här stycket är personligt, det här kommer strömmande."
Till en början verkar det som mer jobb. Då blir det en form av lugn. Prestandabeslut är inte längre dolda i en kombination av standardinställningar, heuristik och stamminne. De finns i koden.
Användbara källor
METADATA
- date: 2026-05-24
- reading: 6 min
- author: Filippo Spinella
- tags: Next.js, React, Frontend, Performance