Eine statisch exportierte Next.js-Website besteht nur aus HTML, CSS, JavaScript und Assets in einem Ordner. Diesen Ordner können Sie auf jeden statischen Hoster legen – Cloudflare Pages, GitHub Pages, S3, Netlify, einen Nginx-Server –, ohne einen Node.js-Server betreiben, patchen oder bezahlen zu müssen. Genau so ist diese Website gebaut.
Dieser Leitfaden zeigt, wie der statische Export im App Router funktioniert, worauf Sie verzichten und wie Sie jede Einschränkung umgehen.
Einschalten
Seit Next.js 14 gibt es next export nicht mehr; der statische Export ist eine Konfigurationsoption:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
// Optional: /about → /about/index.html instead of /about.html
trailingSlash: true,
images: { unoptimized: true },
}
export default nextConfignext build schreibt die Website jetzt nach out/. Eine Vorschau bekommen Sie mit jedem statischen Server:
npx serve outWas funktioniert
Mehr, als viele erwarten:
- Server Components. Sie laufen einmal, beim Build. Daten abrufen, Dateien lesen, APIs aufrufen – das Ergebnis landet fest im HTML.
- Client Components, Hooks, Context und jede clientseitige Bibliothek.
- Dynamische Routen, solange Sie jeden Pfad mit
generateStaticParamsauflisten. - Route Handler mit
GET, die zu statischen Dateien werden (praktisch fürfeed.json,sitemap.xml,robots.txt). - Die Metadata API: Titel, Beschreibungen, Open Graph, kanonische URLs.
- Clientseitige Navigation mit
<Link>und Prefetching.
Was nicht funktioniert – und was Sie stattdessen tun
| Funktion | Warum sie scheitert | Workaround |
|---|---|---|
| Standard-Bildoptimierung | Braucht einen Server | images.unoptimized: true, vorab skalierte Bilder oder ein eigener Loader (Cloudinary, imgix, Cloudflare Images) |
Dynamische Routen ohne generateStaticParams |
Seiten müssen beim Build feststehen | Alle Parameter auflisten; dynamicParams = false setzen |
cookies(), headers(), Daten zur Anfragezeit |
Zur Laufzeit gibt es keine Anfrage | Im Browser lesen oder die Logik in eine API verlagern |
| Server Actions | Brauchen einen Server | Per POST an eine Serverless-Funktion senden (Workers, Lambda) |
| Middleware | Braucht einen Server | Regeln beim Hoster: _redirects, _headers, Edge-Funktionen |
redirects, rewrites, headers in der Konfiguration |
Werden vom Next-Server angewendet | Ebenso: beim Hoster konfigurieren |
ISR / revalidate |
Kein Server zum Neugenerieren | Bei Inhaltsänderungen neu bauen (Git-Push oder Webhook) |
| Eingebautes i18n-Routing | Funktion des Pages Router | Sprachsegmente: app/[lang]/... mit generateStaticParams |
Dynamische Routen richtig gemacht
Jedes dynamische Segment braucht beim Build eine Liste seiner Werte:
import { getAllPosts, getPost } from '@/lib/blog'
import { notFound } from 'next/navigation'
export const dynamicParams = false // unknown slugs are a 404, not a runtime render
export async function generateStaticParams() {
const posts = await getAllPosts()
return posts.map((post) => ({ slug: post.slug }))
}
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params
const post = await getPost(slug)
if (!post) notFound()
return <article dangerouslySetInnerHTML={{ __html: post.html }} />
}Beachten Sie, dass params in Next.js 15 ein Promise ist – mit await auflösen.
Eine Falle: Gibt generateStaticParams ein leeres Array zurück, schlägt der Build fehl, weil die Route keine Seiten erzeugen würde. Kann eine Sammlung leer sein (etwa ein neuer Blog), geben Sie einen Platzhalter-Parameter zurück und lassen ihn eine 404-Seite rendern.
Bilder
Sie haben drei sinnvolle Optionen:
unoptimized: true– und Bilder selbst in der richtigen Größe exportieren (WebP oder AVIF, 1- bis 2-mal die Anzeigebreite). Einfach und schnell, wenn Sie diszipliniert sind.- Ein eigener Loader, der auf ein Bild-CDN zeigt und bei Bedarf skalierte Varianten liefert:
export default function loader({ src, width, quality }) {
return `https://images.example.com/${src}?w=${width}&q=${quality || 75}`
}const nextConfig = {
output: 'export',
images: { loader: 'custom', loaderFile: './image-loader.js' },
}- Ein einfaches
<img>mitsrcset,loading="lazy"und expliziterwidth/height, um Layoutverschiebungen zu vermeiden.
Formulare und alles Serverseitige
Auch eine statische Website kann Formulare, Suche und Logins haben – der Serverteil liegt einfach woanders. Das übliche Muster ist eine kleine Serverless-Funktion, die die Seite per fetch aufruft. Die Lösung dieser Website habe ich in ein serverloses Kontaktformular mit Cloudflare Workers und D1 beschrieben.
Weiterleitungen und Header
Konfigurieren Sie sie beim Hoster. Bei Cloudflare Pages und Netlify wird eine _redirects-Datei aus public/ nach out/ kopiert:
/old-page /new-page 301
/blog/* /journal/:splat 301Und _headers für Caching- und Sicherheits-Header:
/_next/static/*
Cache-Control: public, max-age=31536000, immutableInhalte ohne Server aktualisieren
Da es kein ISR gibt, brauchen Inhaltsänderungen einen neuen Build. Das klingt schlimmer, als es ist: Verbinden Sie den Hoster mit Ihrem Git-Repository, und jeder Push baut und deployt in ein, zwei Minuten. Für Inhalte aus einem CMS richten Sie den Webhook des CMS auf den Deploy-Hook des Hosters. Für einen Blog ist es am einfachsten, Beiträge als Markdown im Repository zu halten – siehe ein Markdown-Blog in Next.js ohne CMS.
Wann der statische Export die falsche Wahl ist
- Seiten, die davon abhängen, wer eingeloggt ist, und auf dem Server gerendert werden.
- Tausende Seiten, die sich alle paar Minuten ändern (die Build-Zeit wächst mit der Seitenzahl).
- Alles, was wirklich zur Anfragezeit gerendert werden muss, etwa personalisierte Preise.
Für Marketing-Websites, Portfolios, Dokumentationen, Blogs und Landingpages ist der statische Export meist die schnellste, günstigste und robusteste Option überhaupt.
Checkliste
-
output: 'export'innext.config - Jede dynamische Route hat
generateStaticParamsunddynamicParams = false - Bilder geregelt (unoptimized, eigener Loader oder
<img>) - Kein
cookies(),headers(), keine Server Actions oder Middleware - Weiterleitungen und Header beim Hoster konfiguriert
- Deployments werden durch Git-Pushes oder CMS-Webhooks ausgelöst
-
out/vor dem ersten Deployment lokal geprüft
Nächster Schritt: Sorgen Sie dafür, dass Suchmaschinen die exportierten Seiten verstehen – technisches SEO für den Next.js App Router.

