verstehen — von Nitro bis zum CDN-Edge
Nuxt 3 mit Nitro bietet mehrere Caching-Schichten, die unabhängig voneinander konfiguriert werden können — Server-seitiger Nitro-Cache, ISR mit Stale-While-Revalidate, CDN-Cache-Control-Headers und Edge-Deployment. Die richtige Kombination dieser Schichten macht den Unterschied zwischen einer Anwendung mit 800 ms TTFB und einer mit 40 ms.
Inhaltsverzeichnis
- 1. Die Caching-Schichten in Nuxt 3
- 2. Nitro-Cache: Server-seitiges Caching für Server Routes
- 3. routeRules: Caching auf Page-Ebene konfigurieren
- 4. ISR in Nuxt 3: Incremental Static Regeneration richtig umsetzen
- 5. Cache-Control-Headers: CDN-Caching steuern
- 6. Cache-Invalidierung: wann und wie Cache-Einträge löschen
- 7. Edge Deployment mit Nitro: Cloudflare Workers und Vercel Edge
- 8. Nitro Storage: verteilter Cache mit Redis und KV-Stores
- 9. Nuxt Caching-Strategien im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Die Caching-Schichten in Nuxt 3
Das Nuxt Caching-Modell besteht aus mehreren unabhängigen Schichten, die unterschiedliche Teile des Request-Response-Zyklus abdecken. Die erste und tiefste Schicht ist der Nitro-Cache: Server-seitiges Caching von Server-Route-Responses in-Memory oder in einem konfigurierten Storage-Backend. Die zweite Schicht sind CDN-Cache-Control-Headers, die dem vorgelagerten CDN mitteilen, wie lange es eine Response zwischenspeichern darf. Die dritte Schicht ist ISR (Incremental Static Regeneration), die statisch vorgerenderte HTML-Seiten mit einer konfigurierbaren Revalidierungszeit kombiniert. Die vierte Schicht ist das Browser-Caching über HTTP-Headers.
Diese Schichten sind unabhängig voneinander konfigurierbar — aber sie interagieren. Eine Server Route mit Nitro-Cache von 60 Sekunden, die einen Cache-Control: public, max-age=3600-Header setzt, wird vom CDN eine Stunde gecacht, unabhängig vom Nitro-Cache-Ablauf. Das ist gewollt, wenn die Daten sich tatsächlich selten ändern — und problematisch, wenn der Nitro-Cache frische Daten hat, das CDN aber noch veraltete. Das Verständnis dieser Interaktion ist der Schlüssel zu einer korrekten Nuxt Caching-Strategie, die weder Daten veraltet liefert noch Performance-Potenzial verschenkt.
Der erste Schritt bei der Planung einer Nuxt Edge-Strategie ist daher eine Klassifizierung der Content-Typen: Wie oft ändern sich diese Daten? Sind sie nutzerabhängig (personalisiert) oder öffentlich? Können veraltete Daten für eine gewisse Zeit toleriert werden? Diese Fragen bestimmen, welche Caching-Schicht(en) für jeden Content-Typ sinnvoll sind. Personalisierte Daten dürfen niemals in einem gemeinsamen CDN-Cache landen. Öffentliche, selten ändernde Daten sind ideal für aggressive Caching-Strategien über alle Schichten.
2. Nitro-Cache: Server-seitiges Caching für Server Routes
Der Nitro Cache ist die leistungsfähigste und flexibelste Caching-Schicht in der Nuxt-3-Architektur. Mit defineCachedEventHandler statt defineEventHandler wird eine Server Route gecacht. Der Cache-Key, die Cache-Dauer und das Cache-Storage-Backend sind pro Route konfigurierbar. Standardmäßig cacht Nitro im Memory — schnell, aber nicht über mehrere Server-Instanzen geteilt. Mit einem externen Storage-Backend wie Redis wird der Cache verteilt und überlebt Server-Neustarts.
Die getKey-Funktion im Nitro-Cache-Konfigurationsobjekt ist entscheidend für die Cache-Granularität. Eine Server Route ohne getKey cacht alle Requests unter demselben Key — problematisch bei Routen, die Query-Parameter oder Locale-Header verarbeiten. Eine getKey-Funktion, die Query-Parameter, Accept-Language-Header oder Nutzer-Segmente einschließt, erstellt granulare Cache-Einträge, die korrekte Responses für verschiedene Request-Varianten liefern. Das ist der Unterschied zwischen einem korrekten und einem kaputten Cache.
// server/api/products/featured.get.ts
// Nitro cached route — respects locale and currency query params in cache key
export default defineCachedEventHandler(async (event) => {
const query = getQuery(event)
const locale = (query.locale as string) ?? 'de'
const currency = (query.currency as string) ?? 'EUR'
// Fetch from external API or DB — result will be cached per locale+currency
const products = await $fetch(`https://api.example.com/products/featured`, {
headers: { 'Accept-Language': locale },
query: { currency },
})
// Set CDN cache headers in addition to Nitro cache
setResponseHeaders(event, {
'Cache-Control': 'public, max-age=300, stale-while-revalidate=60',
})
return products
}, {
maxAge: 60 * 5, // 5 minutes in Nitro cache
// Cache key includes locale and currency — separate entry per combination
getKey: (event) => {
const q = getQuery(event)
return `featured:${q.locale ?? 'de'}:${q.currency ?? 'EUR'}`
},
// Store in Redis for distributed caching across multiple server instances
base: 'redis',
})
3. routeRules: Caching auf Page-Ebene konfigurieren
routeRules in der nuxt.config.ts ist das zentrale Werkzeug für seitenweises Nuxt Caching. Sie erlauben es, für jede URL-Pattern eine eigene Rendering- und Caching-Strategie zu definieren — ohne dass eine einzelne Seite manuell konfiguriert werden muss. Das macht routeRules zum idealen Werkzeug für hybride Anwendungen, in denen verschiedene Seitentypen verschiedene Caching-Anforderungen haben.
Die wichtigsten routeRules-Optionen für Nuxt Caching: prerender: true rendert die Seite einmalig beim Build zu einer statischen HTML-Datei. isr: N implementiert ISR mit einer Revalidierungszeit von N Sekunden — die Seite wird beim ersten Request gerendert, gecacht, und nach N Sekunden bei der nächsten Anfrage im Hintergrund revalidiert. cache: { maxAge: N } cacht die SSR-Response für N Sekunden im Nitro-Cache. ssr: false schaltet auf Client-only-Rendering um — kein Server-seitiges Rendering, kein Caching auf Server-Seite.
// nuxt.config.ts — route-level caching strategy per URL pattern
export default defineNuxtConfig({
routeRules: {
// Marketing pages: pre-rendered once at build time — CDN serves static HTML
'/': { prerender: true },
'/about': { prerender: true },
'/blog': { prerender: true },
// Blog posts: ISR — rendered on first request, revalidated every 10 minutes
'/blog/**': { isr: 600 },
// Product pages: ISR with shorter interval for fresher data
'/products/**': { isr: 120 },
// API routes: Nitro-cached responses, CDN-cacheable
'/api/catalog/**': { cache: { maxAge: 300 } },
// User-specific pages: SSR only, no caching (personalized content)
'/account/**': { ssr: true, cache: false },
// Admin: SPA mode, no SSR, no server cache
'/admin/**': { ssr: false },
},
})
4. ISR in Nuxt 3: Incremental Static Regeneration richtig umsetzen
Incremental Static Regeneration (ISR) ist das Caching-Muster, das den besten Kompromiss zwischen statischer Performance und dynamischer Aktualität bietet. Das Prinzip: Die erste Anfrage für eine URL löst einen Server-Render aus, das Ergebnis wird gecacht. Alle folgenden Anfragen innerhalb der Revalidierungszeit bekommen die gecachte Version — mit Server-Speed, ohne erneuten Render. Nach Ablauf der Revalidierungszeit wird beim nächsten Request die gecachte Version ausgeliefert (Stale-While-Revalidate), während im Hintergrund ein neuer Render gestartet wird. Der nächste Request bekommt die frische Version.
Der Nuxt ISR-Mechanismus über routeRules: { '/products/**': { isr: 300 } } implementiert genau dieses Stale-While-Revalidate-Muster. Der Nutzer wartet niemals auf einen Render — er bekommt immer eine gecachte Version. Die maximale "Veraltungszeit" ist durch den ISR-Wert begrenzt. Für Produktkataloge, Blog-Seiten und andere Inhalte, die sich gelegentlich ändern, aber keine Echtzeit-Aktualität erfordern, ist ISR die optimale Caching-Strategie: schnell wie statisch, aktuell wie SSR, ohne die Infrastruktur-Komplexität von manuellem Cache-Busting.
5. Cache-Control-Headers: CDN-Caching steuern
HTTP Cache-Control-Headers sind die Schnittstelle zwischen dem Nuxt-3-Server und vorgelagerten CDNs wie Cloudflare, AWS CloudFront oder Fastly. Korrekte Headers erlauben dem CDN, Responses zu cachen und direkt aus dem Edge-Netzwerk auszuliefern — ohne den Origin-Server zu kontaktieren. Das reduziert die Server-Last und die Latenz für geographisch verteilte Nutzer drastisch.
Die wichtigsten Cache-Control-Direktiven für Nuxt Edge-Strategien: public erlaubt CDN-Caching von Responses (ohne: CDN cacht standardmäßig nicht). max-age=N definiert die Cache-Lebensdauer in Sekunden aus Sicht des CDN. stale-while-revalidate=M erlaubt das Ausliefern veralteter Responses für M Sekunden, während im Hintergrund revalidiert wird. s-maxage=N definiert die Cache-Lebensdauer nur für CDNs (überschreibt max-age für Shared Caches). no-store verhindert jegliches Caching — Pflicht für personalisierte und sensitive Responses.
6. Cache-Invalidierung: wann und wie Cache-Einträge löschen
Cache-Invalidierung ist das schwierigste Problem beim Nuxt Caching — nicht technisch, sondern konzeptuell. Die Frage "wann muss welcher Cache-Eintrag ungültig werden?" hat keine einfache universelle Antwort. Sie hängt von den Datenabhängigkeiten ab: Wenn ein Produkt aktualisiert wird, müssen der Nitro-Cache für /api/products/[id], die ISR-gecachte /products/[id]-Seite und potenziell die CDN-gecachte Antwort invalidiert werden. Das sind drei verschiedene Systeme mit drei verschiedenen Invalidierungsmechanismen.
Im Nitro-Cache lässt sich ein einzelner Cache-Eintrag programmatisch löschen: useStorage('cache').removeItem(key) entfernt den Eintrag, der nächste Request triggert einen neuen Fetch. Für CDN-Cache ist Invalidierung über die CDN-API nötig — Cloudflare Cache Purge API, Vercel Revalidation Token oder AWS CloudFront Invalidation. Diese CDN-Invalidierungen können aus einer Nuxt-Server-Route ausgelöst werden, die von einem Webhook des Content-Management-Systems aufgerufen wird. Das Muster: CMS ändert Inhalt → Webhook → Nuxt-Route invalidiert Nitro-Cache und CDN-Cache → nächste Page-View bekommt frischen Content.
// server/api/_invalidate.post.ts
// Webhook endpoint — called by CMS when content changes
// Protected by shared secret to prevent unauthorized cache clears
export default defineEventHandler(async (event) => {
// Verify webhook signature
const secret = getHeader(event, 'x-webhook-secret')
if (secret !== process.env.WEBHOOK_SECRET) {
throw createError({ statusCode: 401, message: 'Unauthorized' })
}
const body = await readBody(event)
const { type, id } = body // e.g. { type: 'product', id: 'abc-123' }
if (type === 'product') {
// 1. Invalidate Nitro cache for this product's API route
const storage = useStorage('cache')
await storage.removeItem(`nitro:handlers:/api/products/${id}:product:${id}`)
// 2. Trigger ISR revalidation for the product page
// Nuxt ISR: setting isr: 0 in routeRules for a request forces fresh render
await $fetch(`/products/${id}`, {
headers: { 'x-nuxt-revalidate': process.env.REVALIDATE_SECRET ?? '' }
})
// 3. Purge CDN cache (Cloudflare example)
await $fetch(`https://api.cloudflare.com/client/v4/zones/${process.env.CF_ZONE}/purge_cache`, {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.CF_TOKEN}` },
body: { files: [`https://example.com/products/${id}`] },
})
}
return { success: true, invalidated: `${type}:${id}` }
})
7. Edge Deployment mit Nitro: Cloudflare Workers und Vercel Edge
Nuxt Edge-Deployment mit Nitro bedeutet, die Nuxt-Anwendung nicht auf einem zentralen Server auszuführen, sondern auf Edge-Nodes weltweit — geographisch nahe an den Nutzern. Cloudflare Workers, Vercel Edge Functions und ähnliche Dienste führen JavaScript direkt am CDN-PoP aus. Die Latenz für den ersten Byte sinkt von 200–800 ms (Origin-Request) auf 10–50 ms (Edge-Request), weil kein geographischer Umweg zum Origin-Server nötig ist.
Das Nitro-Preset für Cloudflare Workers (nitro: { preset: 'cloudflare-workers' }) kompiliert den gesamten Server-Code zu einem einzigen Worker-Script, das ohne V8-Node.js-APIs auskommt. Das ist eine wichtige Einschränkung: Node.js-spezifische APIs (fs, path, native Module) funktionieren im Edge-Runtime nicht. Bibliotheken müssen Edge-kompatibel sein. Das ist der häufigste Grund, warum Edge-Deployments scheitern — Abhängigkeiten, die intern Node.js-APIs verwenden. Die Lösung: Edge-Kompatibilität im npm-Paket prüfen oder Server-Middleware auf Edge-kompatible Alternativen umstellen.
8. Nitro Storage: verteilter Cache mit Redis und KV-Stores
Nitro Storage ist das abstrakte Interface, das den Nitro Cache mit verschiedenen Backend-Storages verbindet. In der Entwicklung ist das In-Memory-Storage ausreichend. In der Produktion mit mehreren Server-Instanzen oder Edge-Deployment braucht man ein verteiltes Storage-Backend: Redis für klassisches Server-Deployment, Cloudflare KV oder Vercel KV für Edge-Deployments. Die Konfiguration in nuxt.config.ts via nitro.storage ist konsistent — der Application-Code ändert sich nicht, nur die Backend-Konfiguration.
Redis als Nitro-Storage-Backend bietet gegenüber In-Memory-Cache drei entscheidende Vorteile: Der Cache überlebt Server-Neustarts und Deployments. Mehrere Server-Instanzen teilen denselben Cache — kein Cold-Start-Problem beim Horizontal-Scaling. Redis unterstützt natürlich TTL, sodass Nitro-Cache-Einträge automatisch ablaufen, ohne manuelle Cleanup-Logik. Die Latenz zu einem lokalen Redis-Server (< 1 ms) ist vernachlässigbar gegenüber dem CPU-Aufwand eines SSR-Renders. Das Verhältnis von Cache-Hit-Rate zu Rendering-Overhead macht Redis-backed Nitro-Cache besonders für SSR-Seiten mit hohem Traffic wirtschaftlich.
9. Nuxt Caching-Strategien im Vergleich
Die Wahl der richtigen Nuxt Caching-Strategie hängt von Content-Typ, Update-Frequenz und Personalisierungsanforderungen ab. Die folgende Tabelle zeigt die wichtigsten Strategien und ihre optimalen Einsatzgebiete.
| Strategie | Konfiguration | Optimales Einsatzgebiet | TTFB-Erwartung |
|---|---|---|---|
| Statisches Pre-rendering | prerender: true | Docs, Landing Pages, Blog (selten geändert) | ~20 ms (CDN-Edge) |
| ISR / SWR | isr: 300 | Produkt-, News-, Blog-Seiten mit regelmäßigen Updates | ~30–80 ms (gecacht) |
| Nitro-Cache SSR | cache: { maxAge: 60 } | Öffentliche Seiten mit mittlerer Update-Frequenz | ~50–150 ms (Server) |
| SSR ohne Cache | cache: false | Personalisierte Seiten, Checkout, Profil | ~300–800 ms (Origin) |
| Client-only (SPA) | ssr: false | Admin, Dashboards, Auth-geschützte UIs | Shell sofort, Daten via API |
Die wichtigste Optimierung in der Praxis: statische und gecachte Seiten so weit wie möglich nach vorne schieben, SSR ohne Cache nur für Content einsetzen, der sich in Echtzeit ändern muss oder nutzerspezifisch ist. Eine Produktseite, die für alle Nutzer identisch ist, braucht kein volles SSR ohne Cache — ISR mit einem 5-Minuten-Intervall ist 10-mal schneller und belastet den Origin-Server um 99 % weniger. Diese Entscheidung pro Seitentyp zu treffen ist der größte Performance-Hebel in einer Nuxt Caching-Strategie.
Mironsoft
Nuxt 3 Performance, Caching-Strategien und Edge-Deployment-Architektur
Nuxt-3-Anwendungen, die schnell sind — messbar und reproduzierbar?
Wir analysieren TTFB, Cache-Hit-Rates und CDN-Konfigurationen in bestehenden Nuxt-Projekten und implementieren Nitro-Caching, ISR und Edge-Strategien, die den Unterschied in echten Messwerten zeigen.
Caching-Audit
TTFB-Analyse, Cache-Hit-Rate-Messung und Identifikation von Caching-Lücken
routeRules-Strategie
ISR, Nitro-Cache und CDN-Headers pro Seitentyp konfigurieren und testen
Edge-Deployment
Nitro-Presets für Cloudflare Workers oder Vercel Edge — inklusive Kompatibilitäts-Audit
10. Zusammenfassung
Das Nuxt Caching-Modell bietet mehrere unabhängige Schichten: Nitro-Cache für Server-Route-Responses, routeRules für seitenweises Caching, ISR für Stale-While-Revalidate-Verhalten, Cache-Control-Headers für CDN-Steuerung und Edge-Deployment für geographisch minimierte Latenz. Die richtige Kombination hängt von der Content-Klassifizierung ab: öffentlich vs. personalisiert, statisch vs. dynamisch, häufige vs. seltene Änderungen.
Die größten Performance-Gewinne entstehen durch konsequente Anwendung der Caching-Hierarchie: Statisches Pre-rendering wo möglich, ISR wo Aktualität wichtig ist, SSR ohne Cache nur wo personalisierte Echtzeit-Daten nötig sind. Cache-Invalidierung über Webhooks und programmatische Nitro-Storage-Zugriffe ermöglicht die manuelle Invalidierung bei Content-Updates, ohne Cache-Timeouts abwarten zu müssen. Edge-Deployment mit Nitro-Presets für Cloudflare oder Vercel reduziert die TTFB für globale Nutzer auf Millisekunden — der größte einzelne Performance-Hebel für international genutzte Nuxt Edge-Anwendungen.
Nuxt Caching und Edge-Strategien — Das Wichtigste auf einen Blick
Nitro-Cache
defineCachedEventHandler mit maxAge und granularem getKey. Redis-Backend für verteilten Cache über mehrere Server-Instanzen.
ISR / Stale-While-Revalidate
routeRules: { '/products/**': { isr: 300 } } — gecachte Version sofort, Revalidierung im Hintergrund. Ideal für Produkt- und Blog-Seiten.
Cache-Invalidierung
Webhook → Server Route → Nitro-Storage-Eintrag löschen + CDN Purge API. CMS-gesteuerte Invalidierung ohne Timeout-Wartezeiten.
Edge Deployment
nitro.preset: 'cloudflare-workers' oder 'vercel-edge'. Kein Node.js-API-Zugriff — Edge-Kompatibilität aller Abhängigkeiten prüfen.