Statische Exporte

Next.js ermöglicht den Start als statische Website oder Single-Page Application (SPA), mit der Option, später Server-Funktionen 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 der Client-Seite vermeiden, was die Bundle-Größe reduziert und schnellere Seitenladezeiten ermöglicht.

Da Next.js diesen statischen Export unterstützt, kann er auf jedem Webserver bereitgestellt und gehostet werden, der statische HTML/CSS/JS-Assets bereitstellen kann.

Konfiguration

Um einen statischen Export zu aktivieren, ändern Sie den Ausgabemodus in next.config.js:

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 `/me` -> `/me/`, behält stattdessen `href` bei
  // skipTrailingSlashRedirect: true,

  // Optional: Ändert das Ausgabeverzeichnis `out` -> `dist`
  // distDir: 'dist',
}

module.exports = nextConfig

Nach Ausführung von next build erzeugt Next.js einen out-Ordner, der die HTML/CSS/JS-Assets für Ihre Anwendung enthält.

Unterstützte Funktionen

Der Kern von Next.js wurde für statische Exporte entwickelt.

Server-Komponenten

Bei Ausführung von next build für einen statischen Export werden Server-Komponenten im app-Verzeichnis während des Builds ausgeführt, ähnlich wie bei traditioneller statischer Seiten-Generierung.

Die resultierende Komponente wird in statisches HTML für den initialen Seitenaufruf und eine statische Nutzlast für die Client-Navigation zwischen Routen gerendert. Für Ihre Server-Komponenten sind 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-Komponenten

Wenn Sie Daten auf dem Client abrufen möchten, können Sie eine Client-Komponente 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 clientseitig erfolgen, verhält sich dies wie eine traditionelle SPA. Beispielsweise ermöglicht die folgende Index-Route die Navigation zu verschiedenen Beiträgen auf dem Client:

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 über next/image kann mit einem statischen Export verwendet werden, indem ein benutzerdefinierter Image-Loader in next.config.js definiert wird. Beispielsweise können Sie Bilder mit einem Dienst wie Cloudinary optimieren:

next.config.js
/** @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 entfernten 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-Handler

Route-Handler 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 zwischengespeicherten oder nicht zwischengespeicherten 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-Komponenten werden während next build in HTML vorgerendert. Da Web-APIs wie window, localStorage und navigator auf dem Server nicht verfügbar sind, müssen Sie sicherstellen, dass Sie nur im Browser darauf zugreifen. Beispiel:

'use client';

import { useEffect } from 'react';

export default function ClientComponent() {
  useEffect(() => {
    // Sie haben jetzt Zugriff auf `window`
    console.log(window.innerHeight);
  }, [])

  return ...;
}

Nicht unterstützte Funktionen

Funktionen, die einen Node.js-Server erfordern oder dynamische Logik, die nicht während des Build-Prozesses berechnet werden kann, werden nicht unterstützt:

Der Versuch, diese Funktionen 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 und gehostet werden, der statische HTML/CSS/JS-Assets bereitstellen kann.

Bei Ausführung von next build generiert Next.js den statischen Export in den out-Ordner. Die Verwendung von next export ist nicht mehr erforderlich. Angenommen, Sie haben die folgenden Routen:

  • /
  • /blog/[id]

Nach Ausführung von next build generiert Next.js die folgenden Dateien:

  • /out/index.html
  • /out/404.html
  • /out/blog/post-1.html
  • /out/blog/post-2.html

Wenn Sie einen statischen Host wie Nginx verwenden, können Sie Rewrites von eingehenden Anfragen zu den richtigen Dateien konfigurieren:

nginx.conf
server {
  listen 80;
  server_name acme.com;

  root /var/www/out;

  location / {
      try_files $uri $uri.html $uri/ =404;
  }

  # Dies ist notwendig, wenn `trailingSlash: false`.
  # Kann weggelassen werden, wenn `trailingSlash: true`.
  location /blog/ {
      rewrite ^/blog/(.*)$ /blog/$1.html break;
  }

  error_page 404 /404.html;
  location = /404.html {
      internal;
  }
}

Versionsverlauf

VersionÄnderungen
v13.4.0App Router (Stabil) fügt erweiterte Unterstützung für statische Exporte hinzu, einschließlich React Server Components und Route Handlers.
v13.3.0next export ist veraltet und wurde durch "output": "export" ersetzt