Fractionnement du code avec des importations dynamiques dans Next.js

Améliorer la vitesse de votre application Next.js grâce à des stratégies de fractionnement de code et de chargement intelligent

Qu'allez-vous apprendre ?

Cet article décrit les différents types de division du code et explique comment utiliser des importations dynamiques pour accélérer vos applications Next.js.

Répartition du code basée sur des routes et des composants

Par défaut, Next.js divise votre code JavaScript en fragments distincts pour chaque itinéraire. Lorsque les utilisateurs chargent votre application, Next.js n'envoie que le code nécessaire au routage initial. Lorsque les utilisateurs parcourent l'application, ils récupèrent les fragments associés aux autres routes. La division du code basée sur le routage minimise la quantité de scripts à analyser et compilées simultanément, ce qui réduit le temps de chargement de la page.

Bien que le fractionnement de code basé sur le routage soit une bonne valeur par défaut, vous pouvez optimiser davantage le processus de chargement en répartissant le code au niveau du composant. Si votre application comporte des composants volumineux, il est judicieux de les diviser en fragments distincts. De cette façon, tous les composants volumineux qui ne sont pas essentiels ou qui ne s'affichent que lors de certaines interactions utilisateur (comme un clic sur un bouton) peuvent être chargés de manière différée.

Next.js est compatible avec le import() dynamique, qui vous permet d'importer des modules JavaScript (y compris les composants React) de manière dynamique et de charger chaque importation en tant que fragment distinct. Cela vous permet de diviser le code au niveau du composant et de contrôler le chargement des ressources afin que les utilisateurs ne téléchargent que le code dont ils ont besoin pour la partie du site qu'ils consultent. Dans Next.js, ces composants sont rendu côté serveur par défaut.

Les importations dynamiques en action

Cet article présente plusieurs versions d'une application exemple composée d'une simple page avec un seul bouton. Lorsque tu cliques sur le bouton, tu vois un chiot tout mignon. À mesure que vous parcourez chaque version de l'application, vous verrez en quoi les importations dynamiques diffèrent des importations statiques et comment les utiliser.

Dans la première version de l'application, le chiot vit dans components/Puppy.js. Pour afficher le chiot sur la page, l'application importe le composant Puppy dans index.js avec une instruction d'importation statique:

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

Pour voir comment Next.js regroupe l'application, inspectez la trace réseau dans les outils de développement:

  1. Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran plein écran.

  2. Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.

  3. Cliquez sur l'onglet Réseau.

  4. Cochez la case Désactiver le cache.

  5. Actualisez la page.

Lorsque vous chargez la page, tout le code nécessaire, y compris le composant Puppy.js, est regroupé dans index.js:

Onglet "DevTools Network" affichant six fichiers JavaScript: index.js, app.js, webpack.js, main.js, 0.js et le fichier DLL (bibliothèque de liens dynamiques).

Lorsque vous appuyez sur le bouton Click me (Cliquer ici), seule la requête concernant le JPEG chiot est ajoutée à l'onglet Network (Réseau) :

Onglet "DevTools Network" après le clic sur le bouton, affichant les six mêmes fichiers JavaScript et une image.

L'inconvénient de cette approche est que même si les utilisateurs ne cliquent pas sur le bouton pour voir le chiot, ils doivent charger le composant Puppy, car il est inclus dans index.js. Dans ce petit exemple, ce n'est pas un problème, mais dans les applications réelles, il est souvent très bénéfique de charger des composants volumineux uniquement en cas de nécessité.

Examinez maintenant une deuxième version de l'application, dans laquelle l'importation statique est remplacée par une importation dynamique. Next.js inclut next/dynamic, ce qui permet d'utiliser des importations dynamiques pour tous les composants de Next:

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

// ...

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

Suivez les étapes du premier exemple pour inspecter la trace réseau.

Lorsque vous chargez l'application pour la première fois, seule index.js est téléchargée. Cette fois, il est de moins de 0,5 Ko (il est passé de 37,9 Ko à 37,4 Ko), car il n'inclut pas le code du composant Puppy:

Le réseau des outils de développement affiche les six mêmes fichiers JavaScript, sauf que la taille de index.js est désormais inférieure de 0,5 Ko.

Le composant Puppy se trouve maintenant dans un fragment distinct, 1.js, qui n'est chargé que lorsque vous appuyez sur le bouton:

Onglet "DevTools Network" après le clic sur le bouton, affichant le fichier 1.js supplémentaire et l'image ajoutée en bas de la liste de fichiers.

Dans les applications réelles, les composants sont souvent beaucoup plus volumineux, et leur chargement différé peut réduire la charge utile JavaScript initiale de plusieurs centaines de kilo-octets.

Importations dynamiques avec indicateur de chargement personnalisé

Lorsque vous chargez des ressources en différé, il est recommandé de fournir un indicateur de chargement en cas de retard. Dans Next.js, vous pouvez le faire en fournissant un argument supplémentaire à la fonction dynamic():

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

Pour voir l'indicateur de chargement en action, simulez une connexion réseau lente dans DevTools:

  1. Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran plein écran.

  2. Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.

  3. Cliquez sur l'onglet Réseau.

  4. Cochez la case Désactiver le cache.

  5. Dans la liste déroulante Limitation, sélectionnez 3G rapide.

  6. Appuyez sur le bouton Cliquez ici.

Désormais, lorsque vous cliquez sur le bouton, le chargement du composant prend un certain temps. En attendant, l'application affiche le message "Chargement...".

Écran sombre avec le texte

Importations dynamiques sans rendu côté serveur

Si vous ne devez afficher un composant que côté client (par exemple, un widget de chat), vous pouvez le faire en définissant l'option ssr sur false:

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

Conclusion

Grâce à la prise en charge des importations dynamiques, Next.js vous permet de répartir le code au niveau du composant, ce qui peut réduire les charges utiles JavaScript et améliorer le temps de chargement de l'application. Tous les composants sont affichés par défaut côté serveur. Vous pouvez désactiver cette option chaque fois que nécessaire.