Statische Exporte
Next.js ermöglicht den Start als statische Website oder Single-Page Application (SPA), mit der Option später Server-Features hinzuzufügen.
Bei Ausführung von next build
generiert Next.js eine HTML-Datei pro Route. Durch die Aufteilung einer strikten SPA in einzelne HTML-Dateien kann Next.js unnötigen JavaScript-Code auf Client-Seite vermeiden, was die Bundle-Größe reduziert und schnellere Ladezeiten ermöglicht.
Da Next.js diesen statischen Export unterstützt, kann es auf jedem Webserver bereitgestellt werden, der statische HTML/CSS/JS-Assets servieren kann.
Konfiguration
Um einen statischen Export zu aktivieren, ändern Sie den Ausgabemodus in next.config.js
:
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
output: 'export',
// Optional: Ändert Links `/me` -> `/me/` und erzeugt `/me.html` -> `/me/index.html`
// trailingSlash: true,
// Optional: Verhindert automatische Umleitung `/me` -> `/me/`, behält `href` bei
// skipTrailingSlashRedirect: true,
// Optional: Ändert das Ausgabeverzeichnis `out` -> `dist`
// distDir: 'dist',
}
module.exports = nextConfig
Nach Ausführung von next build
erstellt Next.js einen out
-Ordner mit den HTML/CSS/JS-Assets Ihrer Anwendung.
Unterstützte Features
Der Kern von Next.js wurde für statische Exporte konzipiert.
Server Components
Bei Ausführung von next build
für einen statischen Export werden Server Components im app
-Verzeichnis während des Builds ausgeführt, ähnlich wie bei traditioneller Static-Site-Generierung.
Die resultierende Komponente wird als statisches HTML für den initialen Seitenaufruf gerendert und als statische Payload für Client-seitige Navigation zwischen Routen. Für Server Components sind bei Verwendung des statischen Exports keine Änderungen erforderlich, es sei denn, sie verwenden dynamische Server-Funktionen.
export default async function Page() {
// Dieser Fetch läuft auf dem Server während `next build`
const res = await fetch('https://api.example.com/...')
const data = await res.json()
return <main>...</main>
}
Client Components
Für Client-seitiges Data Fetching können Sie eine Client Component mit SWR verwenden, um Anfragen zwischenzuspeichern.
'use client'
import useSWR from 'swr'
const fetcher = (url: string) => fetch(url).then((r) => r.json())
export default function Page() {
const { data, error } = useSWR(
`https://jsonplaceholder.typicode.com/posts/1`,
fetcher
)
if (error) return 'Fehler beim Laden'
if (!data) return 'Lädt...'
return data.title
}
'use client'
import useSWR from 'swr'
const fetcher = (url) => fetch(url).then((r) => r.json())
export default function Page() {
const { data, error } = useSWR(
`https://jsonplaceholder.typicode.com/posts/1`,
fetcher
)
if (error) return 'Fehler beim Laden'
if (!data) return 'Lädt...'
return data.title
}
Da Routenübergänge client-seitig erfolgen, verhält sich dies wie eine traditionelle SPA. Beispielsweise ermöglicht die folgende Index-Route die Navigation zu verschiedenen Beiträgen auf Client-Seite:
import Link from 'next/link'
export default function Page() {
return (
<>
<h1>Index-Seite</h1>
<hr />
<ul>
<li>
<Link href="/post/1">Beitrag 1</Link>
</li>
<li>
<Link href="/post/2">Beitrag 2</Link>
</li>
</ul>
</>
)
}
import Link from 'next/link'
export default function Page() {
return (
<>
<h1>Index-Seite</h1>
<p>
<Link href="/other">Andere Seite</Link>
</p>
</>
)
}
Bildoptimierung
Bildoptimierung via next/image
kann mit einem statischen Export verwendet werden, indem ein benutzerdefinierter Image Loader in next.config.js
definiert wird. Beispielsweise können Bilder mit einem Dienst wie Cloudinary optimiert werden:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
loader: 'custom',
loaderFile: './my-loader.ts',
},
}
module.exports = nextConfig
Dieser benutzerdefinierte Loader definiert, wie Bilder von einer Remote-Quelle abgerufen werden. Beispielsweise konstruiert der folgende Loader die URL für Cloudinary:
export default function cloudinaryLoader({
src,
width,
quality,
}: {
src: string
width: number
quality?: number
}) {
const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`]
return `https://res.cloudinary.com/demo/image/upload/${params.join(
','
)}${src}`
}
export default function cloudinaryLoader({ src, width, quality }) {
const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`]
return `https://res.cloudinary.com/demo/image/upload/${params.join(
','
)}${src}`
}
Sie können dann next/image
in Ihrer Anwendung verwenden und relative Pfade zu den Bildern in Cloudinary angeben:
import Image from 'next/image'
export default function Page() {
return <Image alt="turtles" src="/turtles.jpg" width={300} height={300} />
}
import Image from 'next/image'
export default function Page() {
return <Image alt="turtles" src="/turtles.jpg" width={300} height={300} />
}
Route Handlers
Route Handlers rendern eine statische Antwort bei Ausführung von next build
. Nur das GET
HTTP-Verb wird unterstützt. Dies kann verwendet werden, um statische HTML-, JSON-, TXT- oder andere Dateien aus gecachten oder ungecachten Daten zu generieren. Beispiel:
export async function GET() {
return Response.json({ name: 'Lee' })
}
export async function GET() {
return Response.json({ name: 'Lee' })
}
Die obige Datei app/data.json/route.ts
wird während next build
in eine statische Datei gerendert und erzeugt data.json
mit dem Inhalt { name: 'Lee' }
.
Wenn Sie dynamische Werte aus der eingehenden Anfrage lesen müssen, können Sie keinen statischen Export verwenden.
Browser APIs
Client Components werden während next build
zu HTML vorgerendert. Da Web APIs wie window
, localStorage
und navigator
auf dem Server nicht verfügbar sind, müssen Sie sicherstellen, dass diese APIs nur im Browser aufgerufen werden. Beispiel:
'use client';
import { useEffect } from 'react';
export default function ClientComponent() {
useEffect(() => {
// Jetzt haben Sie Zugriff auf `window`
console.log(window.innerHeight);
}, [])
return ...;
}
Nicht unterstützte Features
Features, die einen Node.js-Server erfordern oder dynamische Logik, die nicht während des Build-Prozesses berechnet werden kann, werden nicht unterstützt:
- Dynamische Routen mit
dynamicParams: true
- Dynamische Routen ohne
generateStaticParams()
- Route Handlers die auf Request angewiesen sind
- Cookies
- Rewrites
- Redirects
- Headers
- Middleware
- Incremental Static Regeneration
- Bildoptimierung mit dem Standard-
loader
- Draft Mode
Der Versuch, diese Features mit next dev
zu verwenden, führt zu einem Fehler, ähnlich wie das Setzen der dynamic
-Option auf error
im Root-Layout.
export const dynamic = 'error'
Bereitstellung
Mit einem statischen Export kann Next.js auf jedem Webserver bereitgestellt werden, der statische HTML/CSS/JS-Assets servieren kann.
Bei Ausführung von next build
generiert Next.js den statischen Export in den out
-Ordner. Angenommen, Sie haben folgende Routen:
/
/blog/[id]
Nach next build
erzeugt Next.js folgende Dateien:
/out/index.html
/out/404.html
/out/blog/post-1.html
/out/blog/post-2.html
Bei Verwendung eines statischen Hosts wie Nginx können Sie Rewrites von eingehenden Anfragen zu den korrekten Dateien konfigurieren:
server {
listen 80;
server_name acme.com;
root /var/www/out;
location / {
try_files $uri $uri.html $uri/ =404;
}
# Dies ist notwendig bei `trailingSlash: false`.
# Kann weggelassen werden bei `trailingSlash: true`.
location /blog/ {
rewrite ^/blog/(.*)$ /blog/$1.html break;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
}
Versionsverlauf
Version | Änderungen |
---|---|
v14.0.0 | next export wurde zugunsten von "output": "export" entfernt |
v13.4.0 | App Router (Stable) fügt erweiterte Unterstützung für statische Exporte hinzu, inklusive React Server Components und Route Handlers. |
v13.3.0 | next export ist veraltet und wird durch "output": "export" ersetzt |