Migration von Vite
Diese Anleitung hilft dir bei der Migration einer bestehenden Vite-Anwendung zu Next.js.
Warum wechseln?
Es gibt mehrere Gründe, warum ein Wechsel von Vite zu Next.js sinnvoll sein kann:
Langsame anfängliche Seitenladezeit
Wenn du deine Anwendung mit dem Standard-Vite-Plugin für React erstellt hast, ist deine Anwendung eine reine Client-seitige Anwendung. Solche Client-seitigen Anwendungen, auch bekannt als Single-Page-Applications (SPAs), haben oft eine langsame anfängliche Seitenladezeit. Dies geschieht aus mehreren Gründen:
- Der Browser muss warten, bis der React-Code und das gesamte Anwendungs-Bundle heruntergeladen und ausgeführt wurden, bevor dein Code Anfragen zum Laden von Daten senden kann.
- Dein Anwendungscode wächst mit jeder neuen Funktion und zusätzlichen Abhängigkeit.
Kein automatisches Code-Splitting
Das vorherige Problem der langsamen Ladezeiten kann durch Code-Splitting teilweise behoben werden. Wenn du jedoch versuchst, Code-Splitting manuell durchzuführen, verschlechterst du häufig die Performance. Es ist leicht, versehentlich Network-Waterfalls einzuführen, wenn du Code-Splitting manuell durchführst. Next.js bietet automatisches Code-Splitting, das in seinen Router integriert ist.
Network-Waterfalls
Eine häufige Ursache für schlechte Performance sind sequentielle Client-Server-Anfragen zum Laden von Daten. Ein gängiges Muster für das Datenabrufen in einer SPA ist das anfängliche Rendern eines Platzhalters und das anschließende Abrufen von Daten nach dem Mounting der Komponente. Dies bedeutet jedoch, dass eine untergeordnete Komponente, die Daten abruft, erst mit dem Abrufen beginnen kann, wenn die übergeordnete Komponente ihre eigenen Daten geladen hat.
Während das Abrufen von Daten auf dem Client mit Next.js unterstützt wird, bietet es auch die Möglichkeit, das Datenabrufen auf den Server zu verlagern, wodurch Client-Server-Waterfalls eliminiert werden können.
Schnelle und durchdachte Ladezustände
Mit der eingebauten Unterstützung für Streaming durch React Suspense kannst du gezielter bestimmen, welche Teile deiner UI du zuerst und in welcher Reihenfolge laden möchtest, ohne Network-Waterfalls einzuführen.
Dies ermöglicht dir, Seiten zu erstellen, die schneller laden und Layout-Shifts eliminieren.
Wähle die Datenabruf-Strategie
Je nach Bedarf ermöglicht dir Next.js die Wahl der Datenabruf-Strategie auf Seiten- und Komponentenbasis. Du kannst entscheiden, ob du Daten zur Build-Zeit, zur Anforderungszeit auf dem Server oder auf dem Client abrufen möchtest. Du kannst beispielsweise Daten von deinem CMS abrufen und deine Blogbeiträge zur Build-Zeit rendern, die dann effizient auf einem CDN gecacht werden können.
Middleware
Next.js Middleware ermöglicht es dir, Code auf dem Server auszuführen, bevor eine Anfrage abgeschlossen wird. Dies ist besonders nützlich, um zu vermeiden, dass nicht authentifizierte Inhalte kurz angezeigt werden, wenn ein Benutzer eine authentifizierungspflichtige Seite besucht, indem der Benutzer zur Login-Seite umgeleitet wird. Die Middleware ist auch nützlich für Experimente und Internationalisierung.
Eingebaute Optimierungen
Bilder, Schriftarten und Skripte von Drittanbietern haben oft erhebliche Auswirkungen auf die Performance einer Anwendung. Next.js enthält eingebaute Komponenten, die diese automatisch für dich optimieren.
Migrations-Schritte
Unser Ziel bei dieser Migration ist es, so schnell wie möglich eine funktionierende Next.js-Anwendung zu erstellen, damit du dann schrittweise Next.js-Funktionen einführen kannst. Zunächst behalten wir sie als reine Client-seitige Anwendung (SPA) bei, ohne deinen bestehenden Router zu migrieren. Dies minimiert die Wahrscheinlichkeit von Problemen während des Migrationsprozesses und reduziert Merge-Konflikte.
Schritt 1: Next.js-Abhängigkeit installieren
Als Erstes musst du next
als Abhängigkeit installieren:
Schritt 2: Next.js-Konfigurationsdatei erstellen
Erstelle eine next.config.mjs
im Hauptverzeichnis deines Projekts. Diese Datei enthält deine Next.js-Konfigurationsoptionen.
Hinweis: Du kannst entweder
.js
oder.mjs
für deine Next.js-Konfigurationsdatei verwenden.
Schritt 3: TypeScript-Konfiguration aktualisieren
Wenn du TypeScript verwendest, musst du deine tsconfig.json
-Datei mit den folgenden Änderungen aktualisieren, um sie mit Next.js kompatibel zu machen. Wenn du kein TypeScript verwendest, kannst du diesen Schritt überspringen.
- Entferne die Projektreferenz zu
tsconfig.node.json
- Füge
./dist/types/**/*.ts
und./next-env.d.ts
zuminclude
-Array hinzu - Füge
./node_modules
zumexclude
-Array hinzu - Füge
{ "name": "next" }
zumplugins
-Array incompilerOptions
hinzu:"plugins": [{ "name": "next" }]
- Setze
esModuleInterop
auftrue
:"esModuleInterop": true
- Setze
jsx
aufpreserve
:"jsx": "preserve"
- Setze
allowJs
auftrue
:"allowJs": true
- Setze
forceConsistentCasingInFileNames
auftrue
:"forceConsistentCasingInFileNames": true
- Setze
incremental
auftrue
:"incremental": true
Hier ist ein Beispiel einer funktionierenden tsconfig.json
mit diesen Änderungen:
Weitere Informationen zur Konfiguration von TypeScript findest du in der Next.js-Dokumentation.
Schritt 4: Root Layout erstellen
Eine Next.js App Router-Anwendung muss ein Root Layout enthalten, das eine React Server Component ist und alle Seiten deiner Anwendung umschließt. Diese Datei wird auf der obersten Ebene des app
-Verzeichnisses definiert.
Das nächste Äquivalent zur Root Layout-Datei in einer Vite-Anwendung ist die index.html
-Datei, die deine <html>
, <head>
und <body>
-Tags enthält.
In diesem Schritt wandelst du deine index.html
-Datei in eine Root Layout-Datei um:
- Erstelle ein neues
app
-Verzeichnis in deinemsrc
-Verzeichnis. - Erstelle eine neue
layout.tsx
-Datei in diesemapp
-Verzeichnis:
Hinweis: Für Layout-Dateien können die Dateierweiterungen
.js
,.jsx
oder.tsx
verwendet werden.
- Kopiere den Inhalt deiner
index.html
-Datei in die zuvor erstellte<RootLayout>
-Komponente und ersetze diebody.div#root
undbody.script
-Tags durch<div id="root">{children}</div>
:
- Next.js enthält standardmäßig bereits die meta charset- und meta viewport-Tags, sodass du diese aus deinem
<head>
sicher entfernen kannst:
- Alle Metadaten-Dateien wie
favicon.ico
,icon.png
,robots.txt
werden automatisch zum<head>
-Tag der Anwendung hinzugefügt, sofern sie sich im obersten Verzeichnis desapp
-Verzeichnisses befinden. Nach dem Verschieben aller unterstützten Dateien in dasapp
-Verzeichnis kannst du ihre<link>
-Tags sicher löschen:
- Schließlich kann Next.js deine letzten
<head>
-Tags mit der Metadata API verwalten. Verschiebe deine restlichen Metadaten-Informationen in ein exportiertesmetadata
-Objekt:
Mit den obigen Änderungen hast du von der Deklaration in deiner index.html
zu Next.js' konventionsbasiertem Ansatz gewechselt, der in das Framework integriert ist (Metadata API). Dieser Ansatz ermöglicht es dir, die SEO und Web-Teilbarkeit deiner Seiten einfacher zu verbessern.
Schritt 5: Einstiegspunkt-Seite erstellen
In Next.js deklarierst du einen Einstiegspunkt für deine Anwendung durch Erstellen einer page.tsx
-Datei. Das nächste Äquivalent zu dieser Datei in Vite ist deine main.tsx
-Datei. In diesem Schritt richtest du den Einstiegspunkt deiner Anwendung ein.
- Erstelle ein
[[...slug]]
-Verzeichnis in deinemapp
-Verzeichnis.
Da wir in dieser Anleitung zunächst unsere Next.js-Anwendung als SPA (Single Page Application) einrichten möchten, muss dein Seiten-Einstiegspunkt alle möglichen Routen deiner Anwendung abfangen. Erstelle dafür ein neues [[...slug]]
-Verzeichnis in deinem app
-Verzeichnis.
Dieses Verzeichnis ist ein sogenanntes optionales Catch-all Route Segment. Next.js verwendet einen dateibasierte Router, bei dem Verzeichnisse zum Definieren von Routen verwendet werden. Dieses spezielle Verzeichnis stellt sicher, dass alle Routen deiner Anwendung zu seiner enthaltenen page.tsx
-Datei geleitet werden.
- Erstelle eine neue
page.tsx
-Datei im Verzeichnisapp/[[...slug]]
mit folgendem Inhalt:
Hinweis: Für Seiten-Dateien können die Dateierweiterungen
.js
,.jsx
oder.tsx
verwendet werden.
Diese Datei ist eine Server Component. Wenn du next build
ausführst, wird die Datei in ein statisches Asset vorgerendert. Sie erfordert keinen dynamischen Code.
Diese Datei importiert unser globales CSS und teilt generateStaticParams
mit, dass wir nur eine Route generieren werden, die Index-Route unter /
.
Nun verschieben wir den Rest unserer Vite-Anwendung, die nur Client-seitig ausgeführt wird.
Diese Datei ist eine Client Component, definiert durch die 'use client'
-Direktive. Client Components werden immer noch zu HTML vorgerendert auf dem Server, bevor sie an den Client gesendet werden.
Da wir zu Beginn eine reine Client-Anwendung wollen, können wir Next.js so konfigurieren, dass das Vorrendern ab der App
-Komponente deaktiviert wird.
Aktualisiere nun deine Einstiegspunkt-Seite, um die neue Komponente zu verwenden:
Schritt 6: Statische Bild-Importe aktualisieren
Next.js behandelt statische Bild-Importe etwas anders als Vite. Mit Vite gibt der Import einer Bilddatei deren öffentliche URL als String zurück:
Mit Next.js geben statische Bild-Importe ein Objekt zurück. Das Objekt kann dann direkt mit der Next.js <Image>
-Komponente verwendet werden, oder du kannst die src
-Eigenschaft des Objekts mit deinem bestehenden <img>
-Tag verwenden.
Die <Image>
-Komponente bietet die zusätzlichen Vorteile der automatischen Bildoptimierung. Die <Image>
-Komponente setzt automatisch die width
- und height
-Attribute des resultierenden <img>
basierend auf den Bildabmessungen. Dies verhindert Layout-Shifts beim Laden des Bildes. Dies kann jedoch zu Problemen führen, wenn deine App Bilder enthält, bei denen nur eine ihrer Dimensionen gestylt ist, ohne dass die andere auf auto
gesetzt ist. Wenn nicht auf auto
gestylt, wird die Dimension standardmäßig auf den Wert des <img>
-Dimensionsattributs gesetzt, was dazu führen kann, dass das Bild verzerrt erscheint.
Die Beibehaltung des <img>
-Tags reduziert die Anzahl der Änderungen in deiner Anwendung und verhindert die oben genannten Probleme. Du kannst dann optional später zur <Image>
-Komponente migrieren, um von der Bildoptimierung zu profitieren, indem du einen Loader konfigurierst oder zum Standard-Next.js-Server wechselst, der automatische Bildoptimierung bietet.
- Konvertiere absolute Import-Pfade für Bilder aus
/public
in relative Importe:
- Übergib die
src
-Eigenschaft des Bildes anstelle des gesamten Bildobjekts an dein<img>
-Tag:
Alternativ kannst du die öffentliche URL für das Bild-Asset basierend auf dem Dateinamen referenzieren. Zum Beispiel wird public/logo.png
das Bild unter /logo.png
für deine Anwendung bereitstellen, was der src
-Wert wäre.
Warnung: Wenn du TypeScript verwendest, könntest du auf Typfehler stoßen, wenn du auf die
src
-Eigenschaft zugreifst. Du kannst diese vorerst ignorieren. Sie werden am Ende dieser Anleitung behoben.
Schritt 7: Umgebungsvariablen migrieren
Next.js unterstützt .env
Umgebungsvariablen ähnlich wie Vite. Der Hauptunterschied ist das Präfix, das verwendet wird, um Umgebungsvariablen auf der Client-Seite verfügbar zu machen.
- Ändere alle Umgebungsvariablen mit dem Präfix
VITE_
zuNEXT_PUBLIC_
.
Vite stellt einige eingebaute Umgebungsvariablen über das spezielle import.meta.env
-Objekt bereit, die von Next.js nicht unterstützt werden. Du musst ihre Verwendung wie folgt aktualisieren:
import.meta.env.MODE
⇒process.env.NODE_ENV
import.meta.env.PROD
⇒process.env.NODE_ENV === 'production'
import.meta.env.DEV
⇒process.env.NODE_ENV !== 'production'
import.meta.env.SSR
⇒typeof window !== 'undefined'
Next.js bietet auch keine eingebaute BASE_URL
-Umgebungsvariable. Du kannst jedoch trotzdem eine konfigurieren, wenn du sie benötigst:
- Füge Folgendes zu deiner
.env
-Datei hinzu:
- Setze
basePath
aufprocess.env.NEXT_PUBLIC_BASE_PATH
in deinernext.config.mjs
-Datei:
- Aktualisiere die Verwendung von
import.meta.env.BASE_URL
zuprocess.env.NEXT_PUBLIC_BASE_PATH
Schritt 8: Skripte in package.json
aktualisieren
Du solltest jetzt in der Lage sein, deine Anwendung auszuführen, um zu testen, ob du erfolgreich zu Next.js migriert hast. Aber zuvor musst du deine scripts
in deiner package.json
mit Next.js-bezogenen Befehlen aktualisieren und .next
und next-env.d.ts
zu deiner .gitignore
hinzufügen:
Führe jetzt npm run dev
aus und öffne http://localhost:3000
. Du solltest deine Anwendung nun auf Next.js laufen sehen.
Beispiel: Schau dir diesen Pull Request für ein funktionierendes Beispiel einer zu Next.js migrierten Vite-Anwendung an.
Schritt 9: Aufräumen
Du kannst nun deine Codebasis von Vite-bezogenen Artefakten bereinigen:
- Lösche
main.tsx
- Lösche
index.html
- Lösche
vite-env.d.ts
- Lösche
tsconfig.node.json
- Lösche
vite.config.ts
- Deinstalliere Vite-Abhängigkeiten
Nächste Schritte
Wenn alles nach Plan gelaufen ist, hast du jetzt eine funktionierende Next.js-Anwendung, die als Single-Page-Application läuft. Du nutzt jedoch noch nicht die meisten Vorteile von Next.js, aber du kannst jetzt beginnen, schrittweise Änderungen vorzunehmen, um alle Vorteile zu nutzen. Hier sind einige Dinge, die du als Nächstes tun könntest:
- Migriere von React Router zum Next.js App Router um Folgendes zu erhalten:
- Automatisches Code-Splitting
- Streaming Server-Rendering
- React Server Components
- Optimiere Bilder mit der
<Image>
-Komponente - Optimiere Schriftarten mit
next/font
- Optimiere Skripte von Drittanbietern mit der
<Script>
-Komponente - Aktualisiere deine ESLint-Konfiguration zur Unterstützung von Next.js-Regeln