export const revalidate = 3600 legt in einer App-Router-Anwendung ein Revalidierungsintervall auf Segmentebene fest. Mit aktivierten Cache Components steht diese Segmentsteuerung nicht mehr zur Verfügung. Die Migration ist kein Austausch von Direktiven. Cache-Grenzen liegen danach näher an den Funktionen und Komponenten, die Daten laden. Eine mechanische Umstellung scheitert bei Zugriffen auf Cookies oder Header und erzeugt zu viele Cache-Einträge, wenn Sitzungswerte als Argumente einfließen.
Was ändert sich beim Next.js 16 Caching?
Cache Components machen Caching im App Router explizit. Dynamischer Code läuft bei der Anfrage, während use cache die Ergebnisse von Seiten, Komponenten oder Funktionen wiederverwendbar macht. Next.js kann diese Ergebnisse in die vorgerenderte HTML-Shell aufnehmen, sofern innerhalb der Cache-Grenze keine anfragebezogenen Daten gelesen werden.
Die Build-Konfiguration wird in next.config.ts aktiviert:
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
}
export default nextConfig
Die vorgerenderte Shell kommt zuerst. Ein Suspense-Fallback reserviert darin den Platz für Daten, die erst bei der Anfrage vorliegen. Sobald der Server diese Daten aufgelöst hat, streamt React den fertigen Abschnitt in die bestehende Antwort. Vor der Umstellung erfasst ein Cache-Inventar deshalb jede bisherige Cache-Regel und jeden Zugriff auf anfragebezogene Daten.
Bestehende Cache-Konfiguration vor der Migration prüfen
Die Bestandsaufnahme umfasst page.tsx, layout.tsx, Route-Handler und Funktionen für den Datenzugriff. Folgende Fundstellen gehören in das Migrationsprotokoll:
- Die Route-Segment-Einstellungen
revalidate,dynamicundfetchCache - Funktionen mit
unstable_cacheund Aufrufe vonfetchmit Cache-Optionen - Mutationen mit
revalidateTag,updateTagoderrevalidatePath - Zugriffe auf Cookies, Header, Suchparameter, Sitzungen und benutzerspezifische Datensätze
Für jeden Datensatz hält das Protokoll das zulässige Datenalter, den Aktualisierungsauslöser und die betroffenen Seiten fest. Das alte Segmentmodell entfällt. Mit aktivierten Cache Components steuern revalidate, dynamic und fetchCache das Rendering nicht mehr auf die bisherige Weise. Das Protokoll zeigt anschließend, welcher Inhalt in die statische Shell, in eine Cache-Grenze oder in den dynamischen Stream gehört.
Statische Shell, Cache-Grenze oder dynamischer Stream?
| Bereich | Geeignete Inhalte | Umsetzung |
|---|---|---|
| HTML-Shell | Navigation, öffentliches Layout und vorab bekannte Inhalte | Next.js rendert den Bereich vor und liefert ihn ohne Warten auf anfragebezogene Daten aus |
| Cache-Grenze | Produktdaten, Kategorien oder Konfigurationen mit gemeinsamer Lebensdauer | use cache, cacheLife und bei Bedarf cacheTag |
| Dynamischer Stream | Sitzungen, Warenkörbe und Werte aus Cookies oder Headern | Der Zugriff bleibt außerhalb des gemeinsamen Caches und liegt hinter einer Suspense-Grenze |
Argumente und Werte aus dem umgebenden Gültigkeitsbereich fließen in den Schlüssel einer gecachten Funktion ein. Wenige festgelegte Werte, etwa die unterstützte Sprache oder Währung, begrenzen die Zahl der Varianten und lassen sich für viele Anfragen wiederverwenden. Sitzungs-IDs vervielfachen den Cache. Die Schulung Next.js App Router: Skalierbare Webarchitektur vertieft diese Trennung anhand von Server Components, Streaming und Tag-Invalidierung. Nach der Zuordnung erhält jede Cache-Grenze ein passendes cacheLife-Profil.
Von revalidate zu cacheLife migrieren
cacheLife steuert drei Zeitfenster. stale legt fest, wie lange der Client einen Wert verwenden darf, ohne den Server erneut auf aktuellere Daten zu prüfen. Nach revalidate darf der Server einen vorhandenen Wert ausliefern und im Hintergrund erneuern. expire setzt die maximale Lebensdauer. Ist sie überschritten, wartet die Anfrage auf ein neues Ergebnis.
Next.js stellt folgende Profile bereit:
defaultsecondsminuteshoursdaysweeksmax
Abweichende Zeitfenster erhalten ein benanntes Profil in next.config.ts:
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
cacheLife: {
catalog: {
stale: 300,
revalidate: 900,
expire: 3600,
},
},
}
export default nextConfig
Vor der Umstellung gilt das Intervall für das gesamte Route-Segment:
export const revalidate = 3600
export default async function ProductPage({ params }) {
const { slug } = await params
const product = await getProduct(slug)
return <Product product={product} />
}
Danach trägt die wiederverwendbare Komponente ihr Zeitprofil und ihre Tags selbst:
import { cacheLife, cacheTag } from 'next/cache'
async function ProductDetails({ slug }: { slug: string }) {
'use cache'
cacheLife('catalog')
cacheTag('products', `product-${slug}`)
const product = await getProduct(slug)
return <Product product={product} />
}
export default async function ProductPage({ params }) {
const { slug } = await params
return <ProductDetails slug={slug} />
}
Der Tag products invalidiert den gesamten Produktbestand. product-${slug} begrenzt die Invalidierung auf ein Produkt. Das Zeitprofil steuert die normale Alterung, während eine Mutation zwischen sofortigem Verwerfen und Aktualisieren im Hintergrund unterscheiden muss.
updateTag vs. revalidateTag: Entscheidungsmatrix
| API | Verhalten | Einsatz |
|---|---|---|
revalidateTag(tag, 'max') |
Next.js markiert den Eintrag als veraltet und aktualisiert ihn beim nächsten Zugriff im Hintergrund | Veraltete Katalog- oder redaktionelle Daten dürfen während der Aktualisierung ausgeliefert werden |
updateTag(tag) |
Next.js verwirft den Eintrag sofort, sodass der nächste Zugriff auf neue Daten wartet | Eine Server Action braucht nach einer Mutation Read-after-write-Konsistenz |
revalidatePath(path, type) |
Next.js invalidiert die Cache-Daten eines Pfads oder einer durch den Typ bestimmten Route-Hierarchie | Ein konkreter Pfad muss unabhängig von gemeinsam verwendeten Daten-Tags neu gerendert werden |
Die Form revalidateTag(tag) mit nur einem Argument ist veraltet. updateTag ist auf Server Actions beschränkt. In einer Server Action sorgt die Funktion dafür, dass ein nach der Mutation gelesener Datensatz nicht aus dem alten Cache-Eintrag stammt. Vor dieser Entscheidung werden Cookies, Header und Suchparameter aus gemeinsam verwendeten Cache-Grenzen herausgelöst.
Cookies, Header und Suchparameter behandeln
cookies(), headers() und aufgelöste searchParams werden außerhalb einer gemeinsam verwendeten use cache-Funktion gelesen. Ein begrenzter Wert wie eine unterstützte Währung kann anschließend als Argument in den Cache-Schlüssel einfließen. Authentifizierungs-Token, Sitzungsobjekte und persönliche Profile bleiben im dynamischen Abschnitt, weil ihre Aufnahme in gemeinsame Cache-Grenzen unnötig viele Schlüssel erzeugt und bei fehlerhafter Schlüsselbildung Daten offenlegen kann.
Die Zahl möglicher Argumentkombinationen bestimmt die Cache-Kardinalität. Freie Suchtexte, Zeitstempel oder Benutzer-IDs erzeugen fortlaufend neue Schlüssel und verdrängen häufig verwendete Einträge. Bei mehreren Next.js-Instanzen kommt zur Schlüsselgestaltung die Frage hinzu, wo Einträge und Invalidierungsdaten gespeichert werden.
Cache Components mit Docker und Kubernetes betreiben
Eine selbst gehostete Next.js-Anwendung teilt ihren Standard-Cache nicht automatisch zwischen getrennten Instanzen. Zwei Container können deshalb unterschiedliche Datenstände ausliefern, wenn eine Tag-Invalidierung nur den lokalen Cache eines Prozesses erreicht. Ein Neustart entfernt lokale Einträge.
Horizontal skalierte Deployments benötigen einen gemeinsamen Cache-Handler mit einem zentralen Backend, etwa Redis. Der Handler muss sowohl die Cache-Werte als auch die Metadaten für Tags und Invalidierungen instanzübergreifend verwalten. Bei Rolling Deployments laufen alte und neue Replikate zeitweise parallel. Tests verteilen dieselbe Anfragesequenz deshalb bewusst auf beide Versionen und protokollieren die angesprochene Instanz. Cache-Handler, Suspense und Multi-Instanz-Konsistenz behandelt das Next.js Deep Dive Training: Caching & Skalierung; Betriebsmodelle mit Kubernetes finden sich unter Cloud-Native-Training. Ein reproduzierbarer Testplan weist danach nach, ob Lebensdauer und Invalidierung über Instanzwechsel hinweg funktionieren.
Testplan für Datenfrische und Performance
- Ein Baseline-Lauf misst Time to First Byte, Origin-Anfragen und Fehlerraten vor der Umstellung
- Kontrollierte Datenänderungen prüfen die Antworten innerhalb von
stale, nachrevalidateund nachexpire - Eine Mutation mit
updateTagmuss beim nächsten Lesen neue Daten liefern, währendrevalidateTag(tag, 'max')beim nächsten Zugriff zunächst den veralteten Wert ausliefern darf - Mehrere Replikate beantworten dieselbe Anfragesequenz, während das Testprotokoll Cache-Treffer, Datenversion und angesprochene Instanz erfasst
Das Monitoring erfasst die Messwerte getrennt:
- Das Alter der ausgelieferten Daten
- Die Zahl der Cache-Treffer und Cache-Fehler
- Die Fehlerrate der Anwendung
- Die Antwortzeit nach Instanz und Version
- Die Last auf der Datenbank oder der angebundenen API
Für jeden Wert erhält der Produktions-Rollout eine Rückkehrschwelle. Überschreitet der Canary eine dieser Schwellen, greift der vorbereitete Rollback.
Rollback-Checkliste für den Produktions-Rollout
cacheComponents ist eine Build-Konfiguration. Ein vollständiger Laufzeit-Feature-Flag kann die Funktion deshalb nicht unabhängig vom erzeugten Artefakt umschalten. Ein Canary-Deployment mit getrennten Artefakten hält die alte und die neue Konfiguration parallel verfügbar.
- Die Baseline für Datenalter, Latenz, Fehlerrate und Origin-Last ist gespeichert
- Die Rückkehrschwellen für veraltete Daten, steigende Antwortzeiten und zusätzliche Backend-Last sind vorab definiert
- Das vorherige Deployment-Artefakt und seine Next.js-Konfiguration bleiben abrufbar
- Der Canary erhält schrittweise mehr Anfragen, während jede Replikat-Version separat ausgewertet wird
- Container-Neustarts, Rolling Updates und Tag-Invalidierungen wurden über alle Replikate geprüft
Lege vor dem ersten Canary eine Tabelle an, die jede alte Cache-Einstellung ihrer neuen use cache-Grenze, ihrem cacheLife-Profil und ihrem Invalidierungsauslöser zuordnet. Fehlt für einen Eintrag die Lebensdauer oder der Auslöser, bleibt dieser Datenfluss zunächst im alten Deployment.