Codeaufteilung mit dynamischen Importen in Next.js

Hier erfahren Sie, wie Sie Ihre Next.js-App durch Codeaufteilung und intelligente Ladestrategien beschleunigen.

Themen in dieser Anleitung

In diesem Beitrag werden verschiedene Arten der Codeaufteilung erläutert und Sie erfahren, wie Sie mit dynamischen Importen Ihre Next.js-Anwendungen beschleunigen können.

Routenbasierte und komponentenbasierte Codeaufteilung

Standardmäßig teilt Next.js Ihren JavaScript-Code für jede Route in separate Blöcke auf. Wenn Nutzer Ihre Anwendung laden, sendet Next.js nur den Code, der für die anfängliche Route benötigt wird. Wenn Nutzer in der Anwendung navigieren, rufen sie die Blöcke ab, die mit den anderen Routen verknüpft sind. Durch die routenbasierte Codeaufteilung wird die Menge des Skripts minimiert, das gleichzeitig geparst und kompiliert werden muss. Dies führt zu kürzeren Seitenladezeiten.

Die routenbasierte Codeaufteilung ist zwar eine gute Standardeinstellung, Sie können den Ladevorgang aber mit der Codeaufteilung auf Komponentenebene weiter optimieren. Wenn Sie in Ihrer App große Komponenten haben, empfiehlt es sich, diese in separate Blöcke aufzuteilen. Auf diese Weise kann Lazy Loading für alle großen Komponenten eingesetzt werden, die nicht kritisch sind oder nur bei bestimmten Nutzerinteraktionen wie das Klicken auf eine Schaltfläche gerendert werden.

Next.js unterstützt dynamisches import(), mit dem Sie JavaScript-Module (einschließlich React-Komponenten) dynamisch importieren und jeden Import als separaten Block laden können. So erhalten Sie eine Codeaufteilung auf Komponentenebene und können das Laden von Ressourcen steuern, sodass Nutzer nur den Code herunterladen, den sie für den Teil der Website benötigen, den sie sich gerade ansehen. In Next.js werden diese Komponenten standardmäßig serverseitig gerendert (SSR).

Dynamische Importe in Aktion

Dieser Beitrag enthält mehrere Versionen einer Beispiel-App, die aus einer einfachen Seite mit einer Schaltfläche besteht. Wenn du darauf klickst, siehst du einen niedlichen Welpen. Während Sie die einzelnen Versionen der Anwendung durchgehen, werden Sie feststellen, wie sich dynamische Importe von statischen Importen unterscheiden und wie Sie mit ihnen arbeiten.

In der ersten Version der App lebt der Welpe in components/Puppy.js. Damit der Welpe auf der Seite angezeigt wird, importiert die Anwendung die Komponente Puppy mit einer statischen Importanweisung in index.js:

import Puppy from "../components/Puppy";

Wenn Sie wissen möchten, wie Next.js die App bündelt, prüfen Sie den Netzwerk-Trace in den Entwicklertools:

  1. Um die Website als Vorschau anzusehen, wählen Sie App ansehen und dann Vollbild Vollbild aus.

  2. Drücken Sie Strg + Umschalttaste + J (oder Befehlstaste + Option + J auf dem Mac), um die Entwicklertools zu öffnen.

  3. Klicken Sie auf den Tab Netzwerk.

  4. Klicken Sie das Kästchen Cache deaktivieren an.

  5. Lade die Seite neu.

Wenn Sie die Seite laden, wird der gesamte erforderliche Code, einschließlich der Komponente Puppy.js, in index.js gebündelt:

Tab „Network“ der Entwicklertools mit sechs JavaScript-Dateien: index.js, app.js, webpack.js, main.js, 0.js und der dll-Datei (Dynamic-link Library).

Wenn Sie auf die Schaltfläche Click me (Klicken) klicken, wird nur die Anfrage für die Welpen-JPEG-Datei auf dem Tab Network hinzugefügt:

Entwicklertools-Tab „Network“ (Netzwerk) mit den gleichen sechs JavaScript-Dateien und einem Bild.

Der Nachteil dieses Ansatzes besteht darin, dass Nutzer die Puppy-Komponente laden müssen, da sie in index.js enthalten ist, selbst wenn sie nicht auf die Schaltfläche klicken, um den Welpen zu sehen. In diesem kleinen Beispiel ist das kein großes Problem, aber in realen Anwendungen ist es oft eine enorme Verbesserung, große Komponenten nur bei Bedarf zu laden.

Schauen Sie sich nun eine zweite Version der Anwendung an, in der der statische Import durch einen dynamischen Import ersetzt wird. Next.js enthält next/dynamic, wodurch es möglich ist, dynamische Importe für alle Komponenten in Next zu verwenden:

import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";

// ...

const Puppy = dynamic(import("../components/Puppy"));

Führen Sie die Schritte aus dem ersten Beispiel aus, um den Netzwerk-Trace zu prüfen.

Beim ersten Laden der App wird nur index.js heruntergeladen. Dieses Mal ist sie 0,5 KB kleiner (von 37,9 KB auf 37,4 KB reduziert), weil der Code für die Puppy-Komponente nicht enthalten ist:

DevTools-Netzwerk mit denselben sechs JavaScript-Dateien, mit dem Unterschied, dass index.js jetzt 0,5 KB kleiner ist.

Die Komponente Puppy befindet sich jetzt in einem separaten Block namens 1.js, der nur geladen wird, wenn Sie auf die Schaltfläche drücken:

DevTools Network nach dem Klicken auf die Schaltfläche mit der zusätzlichen 1.js-Datei und dem Bild, das am Ende der Dateiliste hinzugefügt wurde.

In realen Anwendungen sind Komponenten häufig viel größer. Durch Lazy Loading kann die anfängliche JavaScript-Nutzlast um Hunderte von Kilobyte gekürzt werden.

Dynamische Importe mit benutzerdefinierter Ladeanzeige

Beim Lazy Loading von Ressourcen empfiehlt es sich, einen Ladeindikator bereitzustellen, falls Verzögerungen auftreten sollten. In Next.js können Sie dafür ein zusätzliches Argument für die Funktion dynamic() angeben:

const Puppy = dynamic(() => import("../components/Puppy"), {
  loading: () => <p>Loading...</p>
});

Um die Ladeanzeige in Aktion zu sehen, simulieren Sie die langsame Netzwerkverbindung in den Entwicklertools:

  1. Um die Website als Vorschau anzusehen, wählen Sie App ansehen und dann Vollbild Vollbild aus.

  2. Drücken Sie Strg + Umschalttaste + J (oder Befehlstaste + Option + J auf dem Mac), um die Entwicklertools zu öffnen.

  3. Klicken Sie auf den Tab Netzwerk.

  4. Klicken Sie das Kästchen Cache deaktivieren an.

  5. Wählen Sie in der Drop-down-Liste Drosselung die Option Schnelles 3G aus.

  6. Klicken Sie auf die Schaltfläche Hier klicken.

Wenn Sie jetzt auf die Schaltfläche klicken, dauert es eine Weile, bis die Komponente geladen ist. In der Zwischenzeit zeigt die App die Meldung „Wird geladen...“ an.

Ein dunkler Bildschirm mit dem Text

Dynamische Importe ohne SSR

Wenn Sie eine Komponente nur clientseitig rendern müssen (z. B. ein Chat-Widget), können Sie dies tun, indem Sie die Option ssr auf false setzen:

const Puppy = dynamic(() => import("../components/Puppy"), {
  ssr: false,
});

Fazit

Da dynamische Importe unterstützt werden, ermöglicht Next.js eine Codeaufteilung auf Komponentenebene. Dadurch können die JavaScript-Nutzlasten minimiert und die Ladezeit von Anwendungen verkürzt werden. Alle Komponenten werden standardmäßig serverseitig gerendert. Sie können diese Option bei Bedarf deaktivieren.