Découvrez comment accélérer votre application Next.js grâce au fractionnement du code et aux stratégies de chargement intelligent.
Date de publication : 8 novembre 2019
Découvrez les différents types de fractionnement du code et comment utiliser les importations dynamiques pour accélérer vos applications Next.js.
Fractionnement du code basé sur les routes et les composants
Par défaut, Next.js divise votre code JavaScript en blocs distincts pour chaque route. Lorsque les utilisateurs chargent votre application, Next.js n'envoie que le code nécessaire pour la route initiale. Lorsque les utilisateurs naviguent dans l'application, ils récupèrent les blocs associés aux autres routes. Le fractionnement du code basé sur les routes minimise la quantité de script qui doit être analysée et compilée en même temps, ce qui permet d'accélérer le temps de chargement des pages.
Bien que la séparation du code basée sur les routes soit une bonne option par défaut, vous pouvez optimiser davantage le processus de chargement en séparant le code au niveau des composants. Si votre application comporte des composants volumineux, il est judicieux de les diviser en blocs distincts. Ainsi, 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 l'importation dynamique import(), qui vous permet d'importer des modules JavaScript (y compris des composants React) de manière dynamique et de charger chaque importation en tant que bloc distinct. Cela vous permet de fractionner le code au niveau des composants 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 rendus côté serveur (SSR, Server-Side Rendering) par défaut.
Les importations dynamiques en action
Cet article inclut plusieurs versions d'une application exemple qui se compose d'une simple page avec un bouton. Lorsque vous cliquez sur le bouton, vous voyez un adorable chiot. Au fur et à 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 pour les développeurs :
Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran
.
Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
Cliquez sur l'onglet Réseau.
Cochez la case Désactiver le cache.
Actualisez la page.
Lorsque vous chargez la page, tout le code nécessaire, y compris le composant Puppy.js, est regroupé dans index.js :
Lorsque vous appuyez sur le bouton Click me (Cliquez ici), seule la requête pour le fichier JPEG du chiot est ajoutée à l'onglet Network (Réseau) :
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 du monde réel, il est souvent très utile de ne charger les grands composants que lorsque cela est nécessaire.
À présent, découvrez 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, seul index.js est téléchargé. Cette fois, il est 0,5 Ko plus petit (il est passé de 37,9 Ko à 37,4 Ko), car il n'inclut pas le code du composant Puppy :
Le composant Puppy se trouve désormais dans un bloc distinct, 1.js, qui n'est chargé que lorsque vous appuyez sur le bouton :
Dans les applications réelles, les composants sont souvent beaucoup plus volumineux. Le chargement différé peut réduire votre charge utile JavaScript initiale de centaines de kilo-octets.
Importations dynamiques avec indicateur de chargement personnalisé
Lorsque vous chargez des ressources de manière différée, 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 les outils de développement :
Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran
.
Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
Cliquez sur l'onglet Réseau.
Cochez la case Désactiver le cache.
Dans la liste déroulante Throttling (Limitation), sélectionnez Fast 3G (3G rapide).
Appuyez sur le bouton Click me (Cliquez ici).
Désormais, lorsque vous cliquez sur le bouton, le chargement du composant prend un certain temps et l'application affiche le message "Chargement…" en attendant.
Importations dynamiques sans SSR
Si vous devez afficher un composant uniquement côté client (un widget de chat, par exemple), 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 diviser le code au niveau des composants, ce qui peut réduire vos charges utiles JavaScript et améliorer le temps de chargement de votre application. Tous les composants sont rendus côté serveur par défaut. Vous pouvez désactiver cette option chaque fois que nécessaire.