Einführung in Single-Page Applications mit Next.js
Next.js bietet umfassende Unterstützung für die Entwicklung von Single-Page Applications (SPAs).
Dies umfasst schnelle Routenübergänge mit Prefetching, clientseitiges Datenabrufen, die Nutzung von Browser-APIs, die Integration mit Drittanbieter-Client-Bibliotheken, die Erstellung statischer Routen und mehr.
Falls Sie bereits eine SPA haben, können Sie zu Next.js migrieren, ohne große Änderungen an Ihrem Code vornehmen zu müssen. Next.js ermöglicht es Ihnen dann, schrittweise Server-Funktionen nach Bedarf hinzuzufügen.
Was ist eine Single-Page Application?
Die Definition einer SPA variiert. Wir definieren eine "strikte SPA" als:
- Client-seitiges Rendering (CSR): Die App wird durch eine HTML-Datei (z.B.
index.html
) bereitgestellt. Jede Route, Seitenübergang und Datenabfrage wird durch JavaScript im Browser verarbeitet. - Keine vollständigen Seitenneuladungen: Anstatt für jede Route ein neues Dokument anzufordern, manipuliert clientseitiges JavaScript das DOM der aktuellen Seite und ruft Daten nach Bedarf ab.
Strikte SPAs benötigen oft große Mengen an JavaScript, die geladen werden müssen, bevor die Seite interaktiv sein kann. Zudem können clientseitige Daten-Wasserfälle schwer zu verwalten sein. Die Entwicklung von SPAs mit Next.js kann diese Probleme lösen.
Warum Next.js für SPAs verwenden?
Next.js kann Ihre JavaScript-Bundles automatisch code-splitten und mehrere HTML-Einstiegspunkte für verschiedene Routen generieren. Dadurch wird vermieden, dass unnötiger JavaScript-Code clientseitig geladen wird, was die Bundle-Größe reduziert und schnellere Seitenladezeiten ermöglicht.
Die next/link
-Komponente prefetched automatisch Routen, was Ihnen die schnellen Seitenübergänge einer strikten SPA bietet, aber mit dem Vorteil, dass der Routing-Zustand der Anwendung in der URL für Verlinkungen und Sharing erhalten bleibt.
Next.js kann als statische Website oder sogar als strikte SPA starten, bei der alles clientseitig gerendert wird. Wenn Ihr Projekt wächst, ermöglicht Next.js Ihnen, schrittweise weitere Server-Funktionen (z.B. React Server Components, Server Actions und mehr) nach Bedarf hinzuzufügen.
Beispiele
Lassen Sie uns gängige Muster zur Entwicklung von SPAs und deren Lösung mit Next.js untersuchen.
Verwendung von Reacts use
innerhalb eines Context Providers
Wir empfehlen, Daten in einer Elternkomponente (oder einem Layout) abzurufen, das Promise zurückzugeben und dann den Wert in einer Client-Komponente mit Reacts use
-Hook zu entpacken.
Next.js kann das Datenabrufen frühzeitig auf dem Server starten. In diesem Beispiel ist das das Root-Layout – der Einstiegspunkt Ihrer Anwendung. Der Server kann sofort mit dem Streamen einer Antwort an den Client beginnen.
Indem Sie Ihr Datenabrufen in das Root-Layout "hochziehen", startet Next.js die angegebenen Anfragen auf dem Server frühzeitig, bevor andere Komponenten Ihrer Anwendung geladen werden. Dies eliminiert clientseitige Wasserfälle und verhindert mehrere Roundtrips zwischen Client und Server. Es kann auch die Leistung erheblich verbessern, da Ihr Server näher (und idealerweise colokalisiert) an Ihrer Datenbank liegt.
Aktualisieren Sie beispielsweise Ihr Root-Layout, um das Promise aufzurufen, aber nicht darauf zu warten.
Während Sie ein einzelnes Promise verzögern und als Prop an eine Client-Komponente übergeben können, sehen wir dieses Muster generell in Kombination mit einem React Context Provider. Dies ermöglicht einen einfacheren Zugriff von Client-Komponenten mit einem benutzerdefinierten React Hook.
Sie können ein Promise an den React Context Provider weiterleiten:
Schließlich können Sie den useUser()
-Hook in jeder Client-Komponente aufrufen und das Promise entpacken:
Die Komponente, die das Promise konsumiert (z.B. Profile
oben), wird suspendiert. Dies ermöglicht partielle Hydration. Sie können das gestreamte und vorgerenderte HTML sehen, bevor JavaScript fertig geladen hat.
SPAs mit SWR
SWR ist eine beliebte React-Bibliothek für das Datenabrufen.
Mit SWR 2.3.0 (und React 19+) können Sie Server-Funktionen schrittweise neben Ihrem bestehenden SWR-basierten clientseitigen Datenabrufcode übernehmen. Dies ist eine Abstraktion des obigen use()
-Musters. Das bedeutet, Sie können das Datenabrufen zwischen Client und Server verschieben oder beides verwenden:
- Nur Client:
useSWR(key, fetcher)
- Nur Server:
useSWR(key)
+ RSC-bereitgestellte Daten - Gemischt:
useSWR(key, fetcher)
+ RSC-bereitgestellte Daten
Beispielsweise können Sie Ihre Anwendung mit <SWRConfig>
und einem fallback
umschließen:
Da dies eine Server-Komponente ist, kann getUser()
sicher Cookies, Header lesen oder mit Ihrer Datenbank kommunizieren. Es wird keine separate API-Route benötigt. Client-Komponenten unterhalb von <SWRConfig>
können useSWR()
mit demselben Schlüssel aufrufen, um die Benutzerdaten abzurufen. Der Komponentencode mit useSWR
erfordert keine Änderungen gegenüber Ihrer bestehenden clientseitigen Abfragelösung.
Die fallback
-Daten können vorgerendert und in der initialen HTML-Antwort enthalten sein, dann sofort in den untergeordneten Komponenten mit useSWR
gelesen werden. SWRs Polling, Revalidierung und Caching laufen weiterhin nur clientseitig, wodurch die gesamte Interaktivität erhalten bleibt, auf die Sie für eine SPA angewiesen sind.
Da die initialen fallback
-Daten automatisch von Next.js verarbeitet werden, können Sie jetzt jegliche bedingte Logik löschen, die zuvor benötigt wurde, um zu prüfen, ob data
undefined
war. Während die Daten geladen werden, wird die nächstgelegene <Suspense>
-Grenze suspendiert.
SWR | RSC | RSC + SWR | |
---|---|---|---|
SSR-Daten | |||
Streaming während SSR | |||
Anfragen deduplizieren | |||
Client-seitige Funktionen |
SPAs mit React Query
Sie können React Query mit Next.js sowohl auf dem Client als auch auf dem Server verwenden. Dies ermöglicht Ihnen, sowohl strikte SPAs zu entwickeln als auch Server-Funktionen in Next.js in Kombination mit React Query zu nutzen.
Erfahren Sie mehr in der React Query-Dokumentation.
Rendern von Komponenten nur im Browser
Client-Komponenten werden während next build
vorgerendert. Wenn Sie das Vorrendern für eine Client-Komponente deaktivieren und sie nur in der Browser-Umgebung laden möchten, können Sie next/dynamic
verwenden:
Dies kann nützlich sein für Drittanbieter-Bibliotheken, die auf Browser-APIs wie window
oder document
angewiesen sind. Sie können auch einen useEffect
hinzufügen, der die Existenz dieser APIs überprüft, und falls sie nicht vorhanden sind, null
oder einen Ladezustand zurückgeben, der vorgerendert würde.
Shallow Routing auf dem Client
Wenn Sie von einer strikten SPA wie Create React App oder Vite migrieren, haben Sie möglicherweise bestehenden Code, der shallow routing verwendet, um den URL-Zustand zu aktualisieren. Dies kann nützlich sein für manuelle Übergänge zwischen Ansichten in Ihrer Anwendung ohne die standardmäßige Next.js Dateisystem-Routing zu verwenden.
Next.js ermöglicht es Ihnen, die nativen Methoden window.history.pushState
und window.history.replaceState
zu verwenden, um den Browser-Verlauf zu aktualisieren, ohne die Seite neu zu laden.
pushState
und replaceState
-Aufrufe integrieren sich in den Next.js Router, sodass Sie sie mit usePathname
und useSearchParams
synchronisieren können.
Erfahren Sie mehr darüber, wie Routing und Navigation in Next.js funktionieren.
Verwendung von Server Actions in Client Components
Sie können Server Actions schrittweise übernehmen, während Sie weiterhin Client Components verwenden. Dadurch können Sie Boilerplate-Code zum Aufrufen einer API-Route entfernen und stattdessen React-Funktionen wie useActionState
verwenden, um Lade- und Fehlerzustände zu handhaben.
Erstellen Sie beispielsweise Ihre erste Server Action:
Sie können eine Server Action vom Client importieren und verwenden, ähnlich wie das Aufrufen einer JavaScript-Funktion. Sie müssen keinen API-Endpunkt manuell erstellen:
Erfahren Sie mehr über Datenmutation mit Server Actions.
Statischer Export (optional)
Next.js unterstützt auch die Generierung einer vollständig statischen Website. Dies hat einige Vorteile gegenüber strikten SPAs:
- Automatisches Code-Splitting: Anstatt ein einzelnes
index.html
auszuliefern, generiert Next.js eine HTML-Datei pro Route, sodass Ihre Besucher den Inhalt schneller erhalten, ohne auf das clientseitige JavaScript-Bundle warten zu müssen. - Verbessertes Benutzererlebnis: Anstatt eines minimalen Skeletts für alle Routen erhalten Sie vollständig gerenderte Seiten für jede Route. Wenn Benutzer clientseitig navigieren, bleiben die Übergänge instantan und SPA-ähnlich.
Um einen statischen Export zu aktivieren, aktualisieren Sie Ihre Konfiguration:
Nach dem Ausführen von next build
erstellt Next.js einen out
-Ordner mit den HTML/CSS/JS-Assets für Ihre Anwendung.
Hinweis: Next.js Server-Funktionen werden bei statischen Exports nicht unterstützt. Erfahren Sie mehr.
Migration bestehender Projekte zu Next.js
Sie können schrittweise zu Next.js migrieren, indem Sie unseren Anleitungen folgen:
Falls Sie bereits eine SPA mit dem Pages Router verwenden, können Sie lernen, wie Sie den App Router schrittweise übernehmen.
Selbsthosting
Erfahren Sie, wie Sie Ihre Next.js-Anwendung auf einem Node.js-Server, als Docker-Image oder als statische HTML-Dateien (statischer Export) selbst hosten können.
Statische Exports
Next.js ermöglicht den Start als statische Website oder Single-Page Application (SPA), mit der Option, später auf Funktionen zu erweitern, die einen Server erfordern.