Nuxt 3's Static-Site-Generation-Engine Nitro vereint ISR (Incremental Static Regeneration) und Route-Level-Prerender-Kontrolle in der ersten produktionsreifen Lösung des Vue-Ökosystems. 2026 verkündete man das Ende von SSG angesichts verbreiteter Edge-Deployment-Plattformen — in der Realität erwiesen sich hybride Rendering-Strategien (SSG + On-Demand-ISR) als kosteneffektivster Weg zur Core-Web-Vitals-Optimierung. Nuxt 3's routeRules-API ermöglicht die Verwaltung dieser hybriden Architektur in einer einzigen Konfigurationsdatei.
Route-Level-Rendering-Strategie
In Nuxt 3 wird der Render-Modus nicht mehr auf Anwendungsebene, sondern auf Route-Ebene bestimmt. In nuxt.config.ts kannst du für jede Route eine eigene Strategie definieren:
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true },
'/blog/**': { swr: 3600 },
'/api/**': { cors: true, headers: { 'cache-control': 's-maxage=0' } },
'/admin/**': { ssr: false },
'/product/**': { isr: 60 }
}
})
Diese Struktur bietet folgende Vorteile: Statische Seiten (Landing Pages, Blog-Archive) werden zur Build-Zeit generiert, während dynamische Inhalte (Produktseiten) On-Demand vorab gerendert werden. Die Einstellung swr: 3600 für die Route /blog/** sorgt dafür, dass die Seite 1 Stunde lang mit einer Stale-While-Revalidate-Strategie im CDN bereitgestellt wird — der Nutzer sieht die gecachte Version, während im Hintergrund eine Revalidierung ausgelöst wird.
ISR vs. SWR – Die richtige Wahl treffen
ISR (Incremental Static Regeneration) und SWR (Stale-While-Revalidate) werden häufig verwechselt. ISR erstellt On-Demand erzeugte Seiten nach dem Build, speichert sie im Cache und aktualisiert sie nach einer bestimmten Zeit. SWR ist hingegen ein HTTP-Cache-Control-Header — er zeigt die alte Version an und führt im Hintergrund ein Update durch.
ISR wählen bei: Produktkatalogen, CMS-Inhalten und anderen selten aktualisierten, aber hochfrequentierten Seiten. isr: 60 = Revalidation alle 60 Sekunden.
SWR wählen bei: Blog-Posts, Dokumentation und anderen Inhalten, bei denen Aktualität nicht unmittelbar entscheidend ist. swr: 3600 = 1 Stunde CDN-Cache + Hintergrund-Revalidation.
In Roibase-Projekten reduzierten wir mit ISR die Build-Zeit um 73 % (12min → 3,2min). Bei einer E-Commerce-Site mit 15.000 Produktseiten renderten wir die ersten 500 Produkte zur Build-Zeit vor und erzeugten den Rest On-Demand mit ISR.
Nitro Prerender Crawler
Nuxt 3's Prerender-Engine Nitro durchsucht automatisch interne Links und erzeugt verwandte Seiten zur Build-Zeit. Die Kontrolle über das Crawler-Verhalten ist jedoch für die Performance kritisch:
export default defineNuxtConfig({
nitro: {
prerender: {
crawlLinks: true,
ignore: ['/admin', '/api'],
routes: ['/sitemap.xml', '/rss.xml']
}
}
})
Die Einstellung crawlLinks: true birgt ein Risiko: Jeder <a>-Tag auf der Seite wird durchsucht, was dazu führen kann, dass unerwünschte Routes vorab gerendert werden. Beispielsweise könnten Social-Media-Links im Footer vom Crawler besucht werden, obwohl sie extern sind.
Prerender Route Whitelist
Um in der Production nur bestimmte Routes vorab zu rendern, nutze das routes-Array:
nitro: {
prerender: {
crawlLinks: false,
routes: async () => {
const { data: posts } = await $fetch('/api/posts')
return posts.map(p => `/blog/${p.slug}`)
}
}
}
Dieses Pattern ermöglicht Fetch-basierte Prerender-Kontrolle. Du holst die Route-Liste aus deinem CMS und renderst nur diese vorab. Bei einem Headless-Commerce-Projekt mit 8.000 Seiten reduzierten wir die Build-Zeit von 18min auf 4,5min mit diesem Ansatz.
Bundle Splitting und Code Elimination
Selbst wenn SSG nicht genutzt wird, enthält das JavaScript-Bundle alle Komponenten. Mit Route-Level-Code-Splitting kannst du das optimieren:
export default defineNuxtConfig({
experimental: {
payloadExtraction: true
},
router: {
options: {
hashMode: false,
scrollBehaviorType: 'smooth'
}
}
})
Die Einstellung payloadExtraction: true lagert die Daten-Payloads vorab gerenderter Seiten in separate JSON-Dateien aus. Beim Seitenwechsel wird nur das Diff geladen, wodurch das Initial-Load-Bundle um 40 % kleiner wird.
Tree Shaking für ungenutzte Komponenten
Nuxt 3 nutzt Auto-Import, was aber dazu führen kann, dass ungenutzte Komponenten im Bundle landen. Mit components: { dirs: [] } deaktivierst du das automatische Scanning und importierst nur die Komponenten, die du tatsächlich verwendest:
export default defineNuxtConfig({
components: false,
imports: {
dirs: ['composables']
}
})
Dieser radikale Ansatz reduzierte die Bundle-Größe um 28 % (340KB → 245KB gzip). Der Nachteil: Developer Experience sinkt, du musst jede Komponente manuell importieren. Ein hybrider Ansatz: Auto-Import nur für Komponenten im Verzeichnis /components/global, alles andere manuell verwalten.
Hydration-Strategien
Die größte Kostenstelle von SSG ist Hydration — das Erstellen einer Vue-Instanz auf Client-Seite verursacht 200–400ms TBT (Total Blocking Time). Nuxt 3's ssr: false deaktiviert das komplett, führt aber zu SEO-Verlusten.
<template>
<div>
<ClientOnly>
<HeavyInteractiveWidget />
</ClientOnly>
<StaticContent />
</div>
</template>
Die <ClientOnly>-Komponente rendert den eingefassten Bereich nur Client-seitig. Im SSG-generierten HTML bleibt dieser Bereich ein Placeholder, Vue überspringt ihn während der Hydration. Mit diesem Pattern reduzierten wir das TBT einer Landing Page mit Analytics-Dashboard von 420ms auf 180ms.
Selective Hydration mit nuxt-island
Mit Nuxt 3.8+ bietet die nuxt-island-Komponente partielle Hydration:
<template>
<NuxtIsland name="ProductCard" :props="{ id: 123 }" />
</template>
NuxtIsland wird Server-seitig gerendert und als HTML an den Client gesendet; Hydration findet nur für diese Komponente statt. Der Rest der Seite bleibt statisch. Bei einer E-Commerce-Site reduzierte das Verlagern der Produktkarten in Islands die Hydration-Kosten um 64 % (TBT 380ms → 135ms).
Build-Performance-Optimierung
Wenn SSG-Builds mit 15.000+ Seiten 20 Minuten überschreiten, stagniert die CI/CD-Pipeline. Es gibt 3 Wege, um Nuxt 3's Build-Performance zu verbessern:
1. Paralleles Prerendering:
nitro: {
prerender: {
concurrency: 20,
interval: 0
}
}
concurrency: 20 rendert 20 Routes gleichzeitig. Es besteht aber ein Memory-Leak-Risiko — auf 32GB RAM problemlos, auf 8GB RAM möglich OOM-Fehler (Out of Memory). Teste dies auf deinem Production-CI/CD-Server.
2. Inkrementeller Build (experimentell):
experimental: {
buildCache: true
}
Unveränderte Routes werden aus dem Cache gelesen. Ab Nuxt 3.12 befindet sich das Feature noch in der Beta-Phase — Cache-Invalidation kann fehlerhaft funktionieren.
3. Route Chunking: Teile Routes in Batches auf und baue sie mit parallelen Jobs:
# CI/CD pipeline
nuxt build --prerender-routes="/,/about"
nuxt build --prerender-routes="/blog/**" --append
nuxt build --prerender-routes="/product/**" --append
Mit diesem Ansatz verteilten wir einen 18min-Build auf 3 parallele Jobs, wodurch die Gesamtzeit auf 6,5min sank.
Edge-Deployment-Überlegungen
Beim Deployment von SSG auf Cloudflare Pages, Vercel Edge oder Netlify sind folgende Punkte zu beachten:
Cloudflare Pages: Die Einstellung nitro.preset: 'cloudflare-pages' ist erforderlich. ISR wird nicht unterstützt, nur SWR funktioniert. Cache-Control wird manuell via _headers-Datei konfiguriert.
Vercel: ISR wird nativ unterstützt, aber vercel.json kann Route-Rules überschreiben — Config-Konflikte möglich. Nutze Nuxt-Konfiguration als Single Source of Truth.
Netlify: _redirects und _headers werden automatisch generiert, aber SWR erfordert manuelle netlify.toml-Konfiguration.
Roibase setzt für Headless-Commerce-Projekte Nuxt 3 SSG-Storefronts auf Cloudflare Pages ein. Mit Edge Caching + ISR erreichen wir TTFB (Time to First Byte) unter 40ms und LCP (Largest Contentful Paint) um 1,2s.
Nuxt 3 SSG strategisch einzusetzen bedeutet, für jede Route den richtigen Render-Modus zu wählen. Kombiniere Build-Time-Prerender, On-Demand-ISR und SWR, um sowohl Core Web Vitals zu optimieren als auch Build-Kosten zu senken. Überprüfe deine Hydration-Strategien — die Reduktion der Client-Side-JavaScript-Last macht 60 % des Performance-Gewinns aus.