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 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 sont automatiquement découpés en morceaux (code split), et vous pouvez utiliser le streaming pour envoyer progressivement des parties de l'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 se comporte de la même manière dans les répertoires app
et pages
pour permettre une migration progressive.
Exemples
Importation de composants clients
'use client'
import { useState } from 'react'
import dynamic from 'next/dynamic'
// Composants clients :
const ComponentA = dynamic(() => import('../components/A'))
const ComponentB = dynamic(() => import('../components/B'))
const ComponentC = dynamic(() => import('../components/C'), { ssr: false })
export default function ClientComponentExample() {
const [showMore, setShowMore] = useState(false)
return (
<div>
{/* Charge immédiatement, mais dans un bundle client séparé */}
<ComponentA />
{/* Charge à la demande, uniquement si la condition est remplie */}
{showMore && <ComponentB />}
<button onClick={() => setShowMore(!showMore)}>Basculer</button>
{/* Charge uniquement côté client */}
<ComponentC />
</div>
)
}
Désactivation du SSR
Lorsque vous utilisez React.lazy()
et Suspense, les composants clients seront pré-rendus (SSR) par défaut.
Si vous souhaitez désactiver le pré-rendu pour un composant client, vous pouvez utiliser l'option ssr
définie sur false
:
const ComponentC = dynamic(() => import('../components/C'), { ssr: false })
Importation de composants serveur
Si vous importez dynamiquement un composant serveur, seuls les composants clients enfants du composant serveur seront chargés de manière différée - pas le composant serveur lui-même.
import dynamic from 'next/dynamic'
// Composant serveur :
const ServerComponent = dynamic(() => import('../components/ServerComponent'))
export default function ServerComponentExample() {
return (
<div>
<ServerComponent />
</div>
)
}
Chargement de bibliothèques externes
Les bibliothèques externes peuvent être chargées à la demande en utilisant la fonction import()
. Cet exemple utilise la bibliothèque externe fuse.js
pour la recherche floue. Le module est uniquement chargé côté client après que l'utilisateur a saisi dans le champ de recherche.
'use client'
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
// Charge dynamiquement 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>
)
}
Ajout d'un composant de chargement personnalisé
import dynamic from 'next/dynamic'
const WithCustomLoading = dynamic(
() => import('../components/WithCustomLoading'),
{
loading: () => <p>Chargement...</p>,
}
)
export default function Page() {
return (
<div>
{/* Le composant de chargement sera affiché pendant que <WithCustomLoading/> charge */}
<WithCustomLoading />
</div>
)
}
Importation d'exports nommés
Pour importer dynamiquement un export nommé, vous pouvez le retourner depuis la Promise retournée par la fonction import()
:
'use client'
export function Hello() {
return <p>Bonjour !</p>
}
import dynamic from 'next/dynamic'
const ClientComponent = dynamic(() =>
import('../components/hello').then((mod) => mod.Hello)
)