spinny:~/writing $ less nextjs-16-cache-components.md
12Eine der nervigsten Fragen in Next.js lautet seit Jahren: „Ist diese Seite statisch oder dynamisch?“. Es scheint eine einfache Frage zu sein, bis Sie einen Aufruf zu `cookies()`, einem `fetch` mit verschiedenen Optionen, einem Datenbank-Client, einem CMS, einem Warenkorb oder einem benutzerdefinierten Inhalt hinzufügen.34Next.js 16 ist interessant, weil es versucht, diese Konversation weniger mysteriös zu gestalten. Dadurch wird die Komplexität nicht beseitigt, aber es verändert das mentale Modell: Routen sind standardmäßig dynamisch, der Cache deklariert sich dort, wo er benötigt wird, und `Suspense` wird zur natürlichen Möglichkeit, schnelle Shells mit Teilen zu erstellen, die frisch bleiben.56Die zu verstehende Funktion sind Cache-Komponenten. Stable Turbopack, React Compiler, `proxy.ts` und die neuen Invalidierungs-APIs sind wichtig, aber sie drehen sich um dasselbe Problem: schnelle Apps zu erstellen, ohne raten zu müssen, was das Framework hinter den Kulissen entschieden hat.78## Weil diese Sache wichtig ist910In einer echten App gibt es nicht nur „statische Seiten“ und „dynamische Seiten“. Sie haben verschiedene Teile mit unterschiedlichen Bedürfnissen.1112Das Produktblatt kann sich mehrmals täglich ändern. Der Preis kann sich öfter ändern. Die Verfügbarkeit muss nahezu live sein. Der Benutzername ist persönlich. Rezensionen können gestreamt werden. Die Seitenleiste kann stabil sein. Der Einkaufswagen funktioniert nicht.1314Wenn man alles als eine Einheit betrachtet, landet man immer in einem von zwei Extremen:1516- aggressives Caching und Risiko, alte Daten zu sehen;17- Überall dynamisches Rendering und schlechtere Leistung als nötig.1819Cache Components dient genau dazu, diese falsche Wahl zu vermeiden.2021## Das Modell in der Praxis2223Mit `cacheComponents: true` können Sie mit `"use cache"` deklarieren, was zwischenspeicherbar ist. Anschließend können Sie Dauer und Tags mit `cacheLife()` und `cacheTag()` verknüpfen. Dynamische Teile bleiben dynamisch und können mit `Suspense` isoliert werden.2425```mermaid26flowchart TD27 Request[Benutzerwunsch] --> Shell[Zwischengespeicherte Shell]28 Request --> Dynamic[Dynamische Abschnitte]29 Shell --> FirstPaint[Erster kurzer Inhalt]30 Dynamic --> Stream[Streaming in Suspense]31 Stream --> Complete[Ganze Seite]32```3334Der Aufbau ist klein:3536```typescript37// next.config.ts38import type { NextConfig } from 'next';3940const nextConfig: NextConfig = {41 cacheComponents: true,42};4344export default nextConfig;45```4647Die große Änderung liegt nicht in der Konfiguration. Es kommt darauf an, wie Sie mit dem Schreiben der Komponenten beginnen.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```9293Die Seite muss nicht vollständig zwischengespeichert oder vollständig dynamisch sein. Das Produktblatt kann schnell und wiederverwendbar sein. Der Bestand kann frisch bleiben. Der Benutzer sieht sofort etwas, ohne auf den langsamsten Teil warten zu müssen.9495## `use cache` ist eine ausführbare Dokumentation9697Was mir an `"use cache"` gefällt, ist, dass es Sie dazu zwingt, eine Absicht deutlich zu machen. Wenn man eine Funktion liest, versteht man sofort, dass jemand entschieden hat: „Diese Daten können wiederverwendet werden“.9899Dies ist besonders nützlich, wenn Sie `fetch` nicht verwenden. Viele Apps lesen Daten von Prisma, Drizzle, internen SDKs, CMS-Clients oder Servicefunktionen. In diesen Fällen reichte die alte Argumentation, die nur auf `fetch`-Optionen basierte, nicht aus.100101Eine Faustregel:102103- Cachea-Inhalt relativ stabil;104- Verwenden Sie granulare Tags.105- hinterlässt dynamische Berechtigungen, Sitzungen, Warenkörbe, Benachrichtigungen und Transaktionsstatus;106- langsame Teile in `Suspense` einfügen;107- messen, bevor wir sagen: „Wir haben die Leistung verbessert“.108109## Ungültig machen, ohne alles wegzuwerfen110111Der Cache ist nur dann nützlich, wenn Sie ihn korrekt aktualisieren können. Hier werden `cacheTag`, `revalidateTag` und `updateTag` wichtig.112113Beispiel: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```129130Das wichtige Detail ist das Etikett. `product:${productId}` gibt eine genaue Grenze an. `products` erzählt einen riesigen Eimer. Zunächst ist der riesige Eimer bequem; Nach ein paar Monaten wird es zum Grund, warum Sie eine halbe App ungültig machen, um einen Titel zu ändern.131132## Stabiler Turbopack: das Teil, das Sie jeden Tag hören133134Next.js 16 bringt Turbopack ins Zentrum für Entwicklung und Build. Es ist nicht gerade das poetischste Feature, aber es ist das, was Sie bei der Arbeit spüren: Server, der früher startet, schnellere Aktualisierung, Builds, die sich nicht mehr wie eine erzwungene Kaffeepause anfühlen.135136Allerdings würde ich eine Codebasis voller benutzerdefinierter Plugins nicht mit geschlossenen Augen migrieren. Ich würde prüfen:137138- lokaler Build;139- Nicht-Standard-Import;140- MDX, SVG und CSS;141- Webpack-Plugins übrig;142- kritische Seiten;143- Unterschiede in den Bauzeiten.144145Bei neuen Projekten würde ich mit der Standardeinstellung beginnen. Für ältere Menschen würde ich eine maßvolle Migration durchführen.146147## Compiler reagieren: Rauschen entfernen, nicht gedacht148149React Compiler 1.0 ist stabil und Next.js 16 unterstützt ihn mit `reactCompiler`. Das Versprechen besteht darin, viele manuelle Auswendiglernen zu reduzieren: weniger `memo`, weniger `useMemo`, weniger `useCallback`, die „aus Sicherheitsgründen“ verwendet werden.150151```typescript152// next.config.ts153import type { NextConfig } from 'next';154155const nextConfig: NextConfig = {156 reactCompiler: true,157};158159export default nextConfig;160```161162Ich würde es nicht wie einen magischen Staub behandeln. Der Compiler hilft, wenn der Code den React-Regeln gut folgt. Wenn Komponenten seltsame Nebenwirkungen, versteckte Mutationen oder falsch verwendete Hooks haben, muss das zuerst behoben werden.163164Die gesunde Art, es auszuprobieren:1651661. aktualisieren `eslint-plugin-react-hooks`;1672. tatsächliche Verstöße beheben;1683. aktivieren Sie es in einem kontrollierten Bereich;1694. Bauzeit und -verhalten messen;1705. Entfernen Sie die manuelle Speicherung nur, wenn sie nicht mehr benötigt wird.171172Das Ziel besteht nicht darin, jedes `useMemo` zu löschen. Das Ziel besteht darin, mit dem Schreiben präventiver Auswendiglernen aufzuhören, weil wir Angst vor dem Rendern haben.173174## `proxy.ts` und die Netzwerkgrenze175176Das alte `middleware.ts` wird zu `proxy.ts`. Es handelt sich um eine Namensänderung, aber sie macht Sinn: Diese Datei befindet sich an der Anforderungsgrenze und ist keine herkömmliche generische Middleware im Backend-Stil.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```192193Die Regel hier ist einfach: Halten Sie es klein. Weiterleitung, Authentifizierungsrouting, Header, wesentliche Umschreibungen. Wenn es sich wie ein zweites Backend anfühlt, macht es wahrscheinlich zu viel.194195## Wie ich wirklich migrieren würde196197Ich würde nicht alle Funktionen auf einmal aktivieren. Ich würde das tun:1981991. Ich aktualisiere Next, React und React DOM;2002. Ich starte den offiziellen Codemod;2013. Ich behebe Breaking Changes an `params`, `searchParams`, `cookies()`, `headers()` und `draftMode()`;2024. Ich migriere `middleware.ts` zu `proxy.ts`;2035. Ich überprüfe Builds und kritische Seiten.2046. Ich aktiviere Cache-Komponenten in einem Abschnitt, in dem der Cache derzeit Reibung verursacht.2057. Ich definiere Konventionen für Tags und Ungültigmachung;2068. Ich versuche React Compiler separat;2079. Vergleich der Kennzahlen vorher und nachher.208209Die gute Migration ist nicht die, die alle neuen Funktionen nutzt. Dadurch wird das Verhalten der App besser lesbar.210211## Was ändert sich in der Denkweise?212213Das Nützlichste an Next.js 16 ist, dass es Sie dazu zwingt, Absichten besser zu benennen. Eine Funktion ist nicht nur „das Produkt aus der Datenbank holen“. Es lautet: „Holen Sie sich das Produkt, ich kann es stundenlang zwischenspeichern, ich mache es mit diesem Tag ungültig.“ Eine Komponente ist nicht nur „die Seite rendern“. Es heißt: „Das ist die schnelle Hülle, dieses Stück ist persönlich, das kommt per Streaming.“214215Auf den ersten Blick scheint es mehr Arbeit zu sein. Dann wird es eine Form der Ruhe. Leistungsentscheidungen sind nicht länger in einer Kombination aus Standardwerten, Heuristiken und Stammesgedächtnis verborgen. Sie stehen im Code.216217## Nützliche Quellen218219- [Versionshinweise zu Next.js 16](https://nextjs.org/blog/next-16)220- [Cache-Komponenten – Next.js-Dokumente](https://nextjs.org/docs/app/getting-started/cache-components)221- [Cache verwenden – Next.js-Dokumente](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-Komponenten und React Compiler: Was sich wirklich ändertlines 1-223 (END) — press q to close