Deployment

Glückwunsch, es ist Zeit für den Produktionsstart.

Sie können Next.js verwaltet mit Vercel bereitstellen oder selbst hosten auf einem Node.js-Server, Docker-Image oder sogar als statische HTML-Dateien. Bei der Bereitstellung mit next start werden alle Next.js-Funktionen unterstützt.

Produktions-Builds

Das Ausführen von next build erzeugt eine optimierte Version Ihrer Anwendung für die Produktion. HTML-, CSS- und JavaScript-Dateien werden basierend auf Ihren Seiten erstellt. JavaScript wird kompiliert und Browser-Bundles werden mit dem Next.js Compiler minifiziert, um die beste Leistung zu erzielen und alle modernen Browser zu unterstützen.

Next.js erzeugt eine standardisierte Deployment-Ausgabe, die sowohl für verwaltete als auch selbst gehostete Next.js-Anwendungen verwendet wird. Dies stellt sicher, dass alle Funktionen in beiden Bereitstellungsmethoden unterstützt werden. In der nächsten Hauptversion werden wir diese Ausgabe in unsere Build Output API-Spezifikation umwandeln.

Next.js verwaltet mit Vercel

Vercel, die Schöpfer und Betreuer von Next.js, bietet eine verwaltete Infrastruktur und eine Developer-Experience-Plattform für Ihre Next.js-Anwendungen.

Die Bereitstellung auf Vercel erfordert keine Konfiguration und bietet zusätzliche Verbesserungen für Skalierbarkeit, Verfügbarkeit und Leistung weltweit. Dennoch werden alle Next.js-Funktionen auch beim Self-Hosting unterstützt.

Erfahren Sie mehr über Next.js auf Vercel oder stellen Sie eine Vorlage kostenlos bereit, um es auszuprobieren.

Self-Hosting

Sie können Next.js auf drei verschiedene Arten selbst hosten:

Node.js-Server

Next.js kann auf jedem Hosting-Anbieter bereitgestellt werden, der Node.js unterstützt. Stellen Sie sicher, dass Ihre package.json die Skripte "build" und "start" enthält:

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}

Führen Sie dann npm run build aus, um Ihre Anwendung zu erstellen. Starten Sie schließlich den Node.js-Server mit npm run start. Dieser Server unterstützt alle Next.js-Funktionen.

Docker-Image

Next.js kann auf jedem Hosting-Anbieter bereitgestellt werden, der Docker-Container unterstützt. Dieser Ansatz eignet sich für die Bereitstellung auf Container-Orchestratoren wie Kubernetes oder für den Betrieb in einem Container bei einem Cloud-Anbieter.

  1. Installieren Sie Docker auf Ihrem Rechner
  2. Klonen Sie unser Beispiel (oder das Multi-Umgebungs-Beispiel)
  3. Erstellen Sie Ihren Container: docker build -t nextjs-docker .
  4. Starten Sie Ihren Container: docker run -p 3000:3000 nextjs-docker

Next.js über Docker unterstützt alle Next.js-Funktionen.

Statischer HTML-Export

Next.js ermöglicht den Start als statische Website oder Single-Page Application (SPA) mit der Option, später auf Funktionen zu upgraden, die einen Server erfordern.

Da Next.js diesen statischen Export unterstützt, kann er auf jedem Webserver bereitgestellt und gehostet werden, der statische Assets wie HTML/CSS/JS bereitstellen kann. Dazu gehören Tools wie AWS S3, Nginx oder Apache.

Der Betrieb als statischer Export unterstützt keine Next.js-Funktionen, die einen Server erfordern. Mehr erfahren.

Gut zu wissen:

Funktionen

Bildoptimierung

Bildoptimierung über next/image funktioniert beim Self-Hosting ohne Konfiguration, wenn Sie next start verwenden. Wenn Sie einen separaten Dienst zur Bildoptimierung bevorzugen, können Sie einen Image Loader konfigurieren.

Bildoptimierung kann mit einem statischen Export verwendet werden, indem ein benutzerdefinierter Image Loader in next.config.js definiert wird. Beachten Sie, dass Bilder zur Laufzeit optimiert werden, nicht während des Builds.

Gut zu wissen:

  • Beim Self-Hosting sollten Sie sharp installieren, um eine leistungsfähigere Bildoptimierung in Ihrer Produktionsumgebung zu erreichen. Führen Sie dazu npm install sharp in Ihrem Projektverzeichnis aus. Auf Linux-Plattformen erfordert sharp möglicherweise zusätzliche Konfiguration, um übermäßigen Speicherverbrauch zu verhindern.
  • Erfahren Sie mehr über das Caching-Verhalten optimierter Bilder und wie Sie die TTL konfigurieren.
  • Sie können auch die Bildoptimierung deaktivieren und dennoch die anderen Vorteile von next/image nutzen, wenn Sie dies bevorzugen. Zum Beispiel, wenn Sie Bilder separat selbst optimieren.

Middleware

Middleware funktioniert beim Self-Hosting ohne Konfiguration, wenn Sie next start verwenden. Da sie Zugriff auf die eingehende Anfrage benötigt, wird sie bei einem statischen Export nicht unterstützt.

Middleware verwendet eine Runtime, die eine Teilmenge aller verfügbaren Node.js-APIs darstellt, um eine niedrige Latenz zu gewährleisten, da sie vor jeder Route oder jedem Asset Ihrer Anwendung ausgeführt werden kann. Diese Runtime erfordert nicht den Betrieb "am Edge" und funktioniert auf einem Single-Region-Server. Zusätzliche Konfiguration und Infrastruktur sind erforderlich, um Middleware in mehreren Regionen auszuführen.

Wenn Sie Logik hinzufügen möchten (oder ein externes Paket verwenden), das alle Node.js-APIs erfordert, können Sie diese Logik möglicherweise in ein Layout als Server Component verschieben. Zum Beispiel das Überprüfen von Headers und Umleitungen. Sie können auch Header, Cookies oder Abfrageparameter verwenden, um über next.config.js Umleitungen oder Rewrites durchzuführen. Falls das nicht funktioniert, können Sie auch einen Custom Server verwenden.

Umgebungsvariablen

Next.js unterstützt sowohl Build-Zeit- als auch Laufzeit-Umgebungsvariablen.

Standardmäßig sind Umgebungsvariablen nur auf dem Server verfügbar. Um eine Umgebungsvariable im Browser verfügbar zu machen, muss sie mit NEXT_PUBLIC_ prefixiert werden. Diese öffentlichen Umgebungsvariablen werden jedoch während next build in das JavaScript-Bundle eingebettet.

Um Laufzeit-Umgebungsvariablen zu lesen, empfehlen wir die Verwendung von getServerSideProps oder die schrittweise Migration zum App Router. Mit dem App Router können Sie Umgebungsvariablen sicher auf dem Server während des dynamischen Renderings lesen. Dies ermöglicht die Verwendung eines einzigen Docker-Images, das durch mehrere Umgebungen mit unterschiedlichen Werten befördert werden kann.

import { unstable_noStore as noStore } from 'next/cache';

export default function Component() {
  noStore();
  // cookies(), headers() und andere dynamische Funktionen
  // werden ebenfalls dynamisches Rendering auslösen,
  // wodurch diese Umgebungsvariable zur Laufzeit ausgewertet wird
  const value = process.env.MY_VALUE
  ...
}

Gut zu wissen:

  • Sie können Code beim Serverstart mit der register-Funktion ausführen.
  • Wir empfehlen nicht die Verwendung der runtimeConfig-Option, da diese nicht mit dem Standalone-Output-Modus funktioniert. Stattdessen empfehlen wir die schrittweise Migration zum App Router.

Caching und ISR

Next.js kann Antworten, generierte statische Seiten, Build-Outputs und andere statische Assets wie Bilder, Schriftarten und Skripts cachen.

Caching und Revalidierung von Seiten (mit Incremental Static Regeneration (ISR) oder neueren Funktionen im App Router) verwenden den gemeinsamen Cache. Standardmäßig wird dieser Cache auf dem Dateisystem (auf der Festplatte) Ihres Next.js-Servers gespeichert. Dies funktioniert automatisch beim Self-Hosting mit sowohl dem Pages- als auch dem App Router.

Sie können den Next.js-Cache-Speicherort konfigurieren, wenn Sie zwischengespeicherte Seiten und Daten in dauerhaften Speicher persistieren oder den Cache über mehrere Container oder Instanzen Ihrer Next.js-Anwendung hinweg teilen möchten.

Automatisches Caching

  • Next.js setzt den Cache-Control-Header von public, max-age=31536000, immutable für wirklich unveränderliche Assets. Dies kann nicht überschrieben werden. Diese unveränderlichen Dateien enthalten einen SHA-Hash im Dateinamen und können daher unbegrenzt zwischengespeichert werden. Zum Beispiel Statische Bildimporte. Sie können die TTL für Bilder konfigurieren.
  • Incremental Static Regeneration (ISR) setzt den Cache-Control-Header auf s-maxage: <revalidate in getStaticProps>, stale-while-revalidate. Diese Revalidierungszeit wird in Ihrer getStaticProps-Funktion in Sekunden definiert. Wenn Sie revalidate: false setzen, wird standardmäßig eine einjährige Cache-Dauer verwendet.
  • Dynamisch gerenderte Seiten setzen einen Cache-Control-Header von private, no-cache, no-store, max-age=0, must-revalidate, um die Zwischenspeicherung benutzerspezifischer Daten zu verhindern. Dies gilt sowohl für den App- als auch den Pages-Router. Dazu gehört auch der Draft Mode.

Statische Assets

Wenn Sie statische Assets auf einer anderen Domain oder einem CDN hosten möchten, können Sie die assetPrefix-Konfiguration in next.config.js verwenden. Next.js verwendet dieses Asset-Präfix beim Abrufen von JavaScript- oder CSS-Dateien. Die Trennung Ihrer Assets auf eine andere Domain hat den Nachteil einer zusätzlichen Zeit für DNS- und TLS-Auflösung.

Mehr über assetPrefix erfahren.

Cache-Konfiguration

Standardmäßig werden generierte Cache-Assets im Speicher (standardmäßig 50 MB) und auf der Festplatte gespeichert. Wenn Sie Next.js mit einer Container-Orchestrierungsplattform wie Kubernetes hosten, hat jeder Pod eine Kopie des Caches. Um zu verhindern, dass veraltete Daten angezeigt werden, da der Cache standardmäßig nicht zwischen Pods geteilt wird, können Sie den Next.js-Cache so konfigurieren, dass er einen Cache-Handler bereitstellt und die In-Memory-Zwischenspeicherung deaktiviert.

Um den ISR/Daten-Cache-Speicherort beim Self-Hosting zu konfigurieren, können Sie einen benutzerdefinierten Handler in Ihrer next.config.js-Datei konfigurieren:

next.config.js
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // Standard-In-Memory-Caching deaktivieren
}

Erstellen Sie dann cache-handler.js im Stammverzeichnis Ihres Projekts, zum Beispiel:

cache-handler.js
const cache = new Map()

module.exports = class CacheHandler {
  constructor(options) {
    this.options = options
  }

  async get(key) {
    // Dies könnte überall gespeichert werden, wie in dauerhaftem Speicher
    return cache.get(key)
  }

  async set(key, data, ctx) {
    // Dies könnte überall gespeichert werden, wie in dauerhaftem Speicher
    cache.set(key, {
      value: data,
      lastModified: Date.now(),
      tags: ctx.tags,
    })
  }

  async revalidateTag(tag) {
    // Durchlaufen Sie alle Einträge im Cache
    for (let [key, value] of cache) {
      // Wenn die Tags des Werts das angegebene Tag enthalten, löschen Sie diesen Eintrag
      if (value.tags.includes(tag)) {
        cache.delete(key)
      }
    }
  }
}

Die Verwendung eines benutzerdefinierten Cache-Handlers ermöglicht es Ihnen, die Konsistenz über alle Pods hinweg sicherzustellen, die Ihre Next.js-Anwendung hosten. Sie können die zwischengespeicherten Werte beispielsweise überall speichern, wie in Redis oder AWS S3.

Gut zu wissen:

  • revalidatePath ist eine bequeme Abstraktionsebene über Cache-Tags. Der Aufruf von revalidatePath ruft die revalidateTag-Funktion mit einem speziellen Standard-Tag für die angegebene Seite auf.

Build-Cache

Next.js generiert während next build eine ID, um zu identifizieren, welche Version Ihrer Anwendung bereitgestellt wird. Derselbe Build sollte verwendet und auf mehreren Containern gestartet werden.

Wenn Sie für jede Stufe Ihrer Umgebung neu bauen, müssen Sie eine konsistente Build-ID generieren, die zwischen Containern verwendet wird. Verwenden Sie den generateBuildId-Befehl in next.config.js:

next.config.js
module.exports = {
  generateBuildId: async () => {
    // Dies könnte alles sein, z.B. der neueste Git-Hash
    return process.env.GIT_HASH
  },
}

Versionsabweichung

Next.js mildert die meisten Fälle von Versionsabweichung automatisch und lädt die Anwendung automatisch neu, um neue Assets abzurufen, wenn eine Abweichung erkannt wird. Beispielsweise führt eine Nichtübereinstimmung in der deploymentId zu einer harten Navigation zwischen Seiten anstelle der Verwendung eines vorab abgerufenen Werts.

Wenn die Anwendung neu geladen wird, kann der Anwendungszustand verloren gehen, wenn er nicht für die Persistenz zwischen Seitenaufrufen ausgelegt ist. Beispielsweise bleiben URL-Zustände oder lokaler Speicher nach einem Seitenrefresh erhalten. Komponentenzustände wie useState gehen jedoch bei solchen Navigationen verloren.

Vercel bietet zusätzlichen Skew-Schutz für Next.js-Anwendungen, um sicherzustellen, dass Assets und Funktionen der vorherigen Version für ältere Clients verfügbar bleiben, selbst nach der Bereitstellung der neuen Version.

Sie können die deploymentId-Eigenschaft manuell in Ihrer next.config.js-Datei konfigurieren, um sicherzustellen, dass jede Anfrage entweder den ?dpl-Query-String oder den x-deployment-id-Header verwendet.

Manuelles Graceful Shutdown

Beim Self-Hosting möchten Sie möglicherweise Code ausführen, wenn der Server bei SIGTERM- oder SIGINT-Signalen herunterfährt.

Sie können die Umgebungsvariable NEXT_MANUAL_SIG_HANDLE auf true setzen und dann einen Handler für dieses Signal in Ihrer _document.js-Datei registrieren. Die Umgebungsvariable muss direkt im package.json-Skript registriert werden, nicht in der .env-Datei.

Gut zu wissen: Die manuelle Signalbehandlung ist in next dev nicht verfügbar.

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "NEXT_MANUAL_SIG_HANDLE=true next start"
  }
}
pages/_document.js
if (process.env.NEXT_MANUAL_SIG_HANDLE) {
  process.on('SIGTERM', () => {
    console.log('Received SIGTERM: cleaning up')
    process.exit(0)
  })
  process.on('SIGINT', () => {
    console.log('Received SIGINT: cleaning up')
    process.exit(0)
  })
}