spinny:~/writing $ vim nextjs-16-cache-components.md
1~2Eine 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.3~4Next.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.5~6Die 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.7~8## Weil diese Sache wichtig ist9~10In einer echten App gibt es nicht nur „statische Seiten“ und „dynamische Seiten“. Sie haben verschiedene Teile mit unterschiedlichen Bedürfnissen.11~12Das 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.13~14Wenn man alles als eine Einheit betrachtet, landet man immer in einem von zwei Extremen:15~16- aggressives Caching und Risiko, alte Daten zu sehen;17- Überall dynamisches Rendering und schlechtere Leistung als nötig.18~19Cache Components dient genau dazu, diese falsche Wahl zu vermeiden.20~21## Das Modell in der Praxis22~23Mit `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.24~25```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```33~34Der Aufbau ist 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~47Die große Änderung liegt nicht in der Konfiguration. Es kommt darauf an, wie Sie mit dem Schreiben der Komponenten beginnen.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~93Die 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.94~95## `use cache` ist eine ausführbare Dokumentation96~97Was 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“.98~99Dies 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.100~101Eine Faustregel:102~103- 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“.108~109## Ungültig machen, ohne alles wegzuwerfen110~111Der Cache ist nur dann nützlich, wenn Sie ihn korrekt aktualisieren können. Hier werden `cacheTag`, `revalidateTag` und `updateTag` wichtig.112~113Beispiel: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~130Das 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.131~132## Stabiler Turbopack: das Teil, das Sie jeden Tag hören133~134Next.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.135~136Allerdings würde ich eine Codebasis voller benutzerdefinierter Plugins nicht mit geschlossenen Augen migrieren. Ich würde prüfen:137~138- lokaler Build;139- Nicht-Standard-Import;140- MDX, SVG und CSS;141- Webpack-Plugins übrig;142- kritische Seiten;143- Unterschiede in den Bauzeiten.144~145Bei neuen Projekten würde ich mit der Standardeinstellung beginnen. Für ältere Menschen würde ich eine maßvolle Migration durchführen.146~147## Compiler reagieren: Rauschen entfernen, nicht gedacht148~149React 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.150~151```typescript152// next.config.ts153import type { NextConfig } from 'next';154~155const nextConfig: NextConfig = {156 reactCompiler: true,157};158~159export default nextConfig;160```161~162Ich 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.163~164Die gesunde Art, es auszuprobieren:165~1661. 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.171~172Das 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.173~174## `proxy.ts` und die Netzwerkgrenze175~176Das 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.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~193Die 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.194~195## Wie ich wirklich migrieren würde196~197Ich würde nicht alle Funktionen auf einmal aktivieren. Ich würde das tun:198~1991. 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.208~209Die gute Migration ist nicht die, die alle neuen Funktionen nutzt. Dadurch wird das Verhalten der App besser lesbar.210~211## Was ändert sich in der Denkweise?212~213Das 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.“214~215Auf 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.216~217## Nützliche Quellen218~219- [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~
NORMAL · nextjs-16-cache-components.md [readonly]223 lines · :q to close