Chargement différé (Lazy Loading)
Le chargement différé dans Next.js aide à améliorer les performances de chargement initial d'une application en réduisant la quantité de JavaScript nécessaire pour rendre une route.
Il vous permet de différer le chargement des composants clients (Client Components) et des bibliothèques importées, et de ne les inclure dans le bundle client que lorsqu'ils sont nécessaires. Par exemple, vous pourriez vouloir différer le chargement d'une modale jusqu'à ce qu'un utilisateur clique pour l'ouvrir.
Il existe deux façons d'implémenter le chargement différé dans Next.js :
- En utilisant les importations dynamiques avec
next/dynamic
- En utilisant
React.lazy()
avec Suspense
Par défaut, les composants serveur (Server Components) sont automatiquement découpés en morceaux (code split), et vous pouvez utiliser le streaming pour envoyer progressivement des éléments d'interface du serveur vers le client. Le chargement différé s'applique aux composants clients.
next/dynamic
next/dynamic
est une combinaison de React.lazy()
et Suspense. Il fonctionne de la même manière dans les répertoires app
et pages
pour permettre une migration progressive.
Exemples
En utilisant next/dynamic
, le composant header ne sera pas inclus dans le bundle JavaScript initial de la page. La page affichera d'abord le fallback
de Suspense, suivi du composant Header
lorsque la limite de Suspense
est résolue.
import dynamic from 'next/dynamic'
const DynamicHeader = dynamic(() => import('../components/header'), {
loading: () => <p>Chargement...</p>,
})
export default function Home() {
return <DynamicHeader />
}
Bon à savoir : Dans
import('chemin/vers/composant')
, le chemin doit être explicitement écrit. Il ne peut pas s'agir d'une chaîne de modèle ni d'une variable. De plus, l'import()
doit être à l'intérieur de l'appeldynamic()
pour que Next.js puisse faire correspondre les bundles webpack / les identifiants de module à l'appeldynamic()
spécifique et les précharger avant le rendu.dynamic()
ne peut pas être utilisé à l'intérieur du rendu React car il doit être marqué au niveau supérieur du module pour que le préchargement fonctionne, similairement àReact.lazy
.
Avec des exportations nommées
Pour importer dynamiquement une exportation nommée, vous pouvez la retourner depuis la Promise renvoyée par import()
:
export function Hello() {
return <p>Bonjour !</p>
}
// pages/index.js
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() =>
import('../components/hello').then((mod) => mod.Hello)
)
Sans SSR
Pour charger dynamiquement un composant côté client, vous pouvez utiliser l'option ssr
pour désactiver le rendu côté serveur. Ceci est utile si une dépendance externe ou un composant repose sur des APIs navigateur comme window
.
import dynamic from 'next/dynamic'
const DynamicHeader = dynamic(() => import('../components/header'), {
ssr: false,
})
Avec des bibliothèques externes
Cet exemple utilise la bibliothèque externe fuse.js
pour la recherche floue. Le module n'est chargé dans le navigateur qu'après que l'utilisateur ait saisi une recherche.
import { useState } from 'react'
const names = ['Tim', 'Joe', 'Bel', 'Lee']
export default function Page() {
const [results, setResults] = useState()
return (
<div>
<input
type="text"
placeholder="Rechercher"
onChange={async (e) => {
const { value } = e.currentTarget
// Chargement dynamique de fuse.js
const Fuse = (await import('fuse.js')).default
const fuse = new Fuse(names)
setResults(fuse.search(value))
}}
/>
<pre>Résultats : {JSON.stringify(results, null, 2)}</pre>
</div>
)
}