Fractionner le code JavaScript (code splitting)
Découpez votre JavaScript en blocs et ne chargez que le nécessaire au démarrage pour accélérer l'affichage et fluidifier les interactions.
Le chargement de fichiers JavaScript volumineux a un impact direct sur la vitesse perçue d’une page. Quand le navigateur doit télécharger, analyser puis compiler un script trop lourd, le thread principal reste occupé et la page peut sembler figée : les éléments sont visibles, stylés par le CSS, mais ne réagissent pas encore aux clics.
Le fractionnement du code (ou code splitting) consiste à diviser un bundle en plusieurs morceaux, puis à ne charger au démarrage que le code strictement nécessaire. Le reste est différé et téléchargé plus tard, au moment où l’utilisateur en a réellement besoin. Pour le SEO, l’enjeu est concret : un thread principal moins encombré améliore la réactivité au chargement, ce qui se répercute positivement sur l’INP (Interaction to Next Paint), un signal d’expérience utilisateur suivi par Google ; cette technique va de pair avec l’effort pour réduire le coût de démarrage du JavaScript.
Le réflexe à prendre, c’est de cesser de tout envoyer au démarrage. Je vois régulièrement des bundles monolithiques où l’utilisateur télécharge le code de fonctionnalités qu’il n’atteindra peut-être jamais. Le fractionnement via les imports dynamiques est l’un des leviers les plus rentables pour une page qui semble figée alors qu’elle est déjà affichée.
Pourquoi réduire le JavaScript exécuté au démarrage
L’analyse et l’exécution de JavaScript se font sur le thread principal. Si cette phase dure trop longtemps, les interactions de l’utilisateur risquent de rester sans réponse, surtout pendant le chargement initial, moment où les visiteurs sont le plus susceptibles d’agir.
Le temps de blocage total (TBT), une métrique de réactivité au chargement, est d’ailleurs fortement corrélé à l’INP. Lighthouse signale un avertissement lorsque l’exécution de JavaScript dépasse deux secondes, et un échec au-delà de 3,5 secondes. L’audit qui détaille le temps passé par chaque script vous aide à repérer les candidats au fractionnement, complété par l’outil de couverture des outils pour développeurs Chrome, qui révèle le code non utilisé au chargement ; pour aller plus loin, voyez comment optimiser les longues tâches qui monopolisent le thread principal.
Mettre en place le fractionnement avec l'import dynamique
Le fractionnement repose sur la syntaxe import() dynamique. Contrairement à une balise script qui réclame une ressource dès le démarrage, l’import dynamique demande un module à un moment ultérieur du cycle de vie de la page. C’est une opération asynchrone, idéale pour charger un module en réponse à une interaction, et un levier de plus pour optimiser le chargement des ressources.
Dans l’exemple suivant, la logique de validation n’est téléchargée que lorsque l’utilisateur quitte un champ du formulaire : le code n’intervient que lorsqu’il a de fortes chances d’être utile.
document.querySelectorAll('#myForm input').forEach((el) => {
el.addEventListener('blur', async () => {
// Import dynamique du module de validation au moment utile :
const { validateForm } = await import('/validate-form.mjs');
validateForm();
}, { once: true });
});
Les outils et options de fractionnement
Les bundlers reconnaissent les appels import() dynamiques et créent automatiquement des blocs séparés. Avec webpack, le plug-in SplitChunksPlugin pilote ce découpage via l’option chunks, qui distingue les imports dynamiques des imports statiques.
| Outil ou option | Type | Rôle |
|---|---|---|
import() dynamique |
Syntaxe JavaScript |
Demande un module plus tard, au moment opportun |
SplitChunksPlugin (webpack) |
Plug-in de bundler |
Configure la façon de découper les fichiers JavaScript |
chunks: async |
Option webpack |
Cible les appels import() dynamiques (valeur par défaut) |
chunks: initial |
Option webpack |
Cible les imports statiques |
chunks: all |
Option webpack |
Couvre les imports dynamiques et statiques |
maxSize |
Option webpack |
Découpe un bloc trop volumineux en fichiers plus petits |
React.lazy |
Abstraction React |
Repose sur import() dynamique en coulisses |
Le moteur V8 applique une compilation en flux continu au JavaScript qui n’utilise pas de modules. Si vous livrez des modules en production, utilisez l’extension .mjs : avec l’extension .js, V8 désactive de fait cette optimisation pour le code basé sur les modules. Pensez aussi à toujours regrouper vos modules avec un bundler, car un arbre de modules non groupé multiplie les requêtes HTTP et retarde l’interactivité.
À faire
- utiliser un bundler en production
- différer le code non critique via import() dynamique
- équilibrer taille des blocs, compression et mise en cache
À éviter
- expédier de nombreux modules non groupés sur le réseau
- livrer des modules en .js plutôt qu’en .mjs
- fractionner à l’excès au point de pénaliser la compression et le cache
Points clés à retenir
- Identifier le code inutile au démarrage avec l'outil de couverture
- Différer les modules secondaires via import() dynamique
- Confier le découpage à un bundler configuré correctement
- Conserver l'extension .mjs pour les modules en production
- Trouver l'équilibre entre cache, compression et temps d'évaluation
Le fractionnement réduit la charge JavaScript initiale et améliore la réactivité.
Quiz : testez vos connaissances
Quiz : testez vos connaissances
-
Sur quelle syntaxe repose le fractionnement du code JavaScript ?
- Une balise script classique qui réclame toutes les ressources dès le démarrage
- L'attribut media appliqué directement sur les fichiers JavaScript
- L'import() dynamique, qui charge un module à un moment ultérieur du cycle de vie de la page
Le fractionnement utilise la syntaxe
import()dynamique : c’est une opération asynchrone qui demande un module plus tard, contrairement à une balise script qui charge tout au démarrage. -
Pourquoi est-il important de réduire le JavaScript exécuté au démarrage ?
- Parce que l'analyse et l'exécution se font sur le thread principal, et qu'une phase trop longue rend les interactions sans réponse
- Parce que le JavaScript de démarrage est le seul que les moteurs de recherche ignorent
- Parce que le thread principal n'exécute jamais le code chargé après le premier rendu
L’analyse et l’exécution du JavaScript occupent le thread principal. Si cette phase dure trop, les interactions de l’utilisateur restent sans réponse, surtout pendant le chargement initial.
-
Faut-il fractionner le code en un maximum de petits blocs ?
- Non, car des fichiers trop petits compressent moins bien et multiplient les allers-retours réseau
- Oui, plus les blocs sont nombreux et petits, meilleure est toujours la performance
- Oui, mais uniquement si chaque bloc contient un seul caractère
Fractionner à l’excès est contre-productif : des blocs trop petits se compressent mal et génèrent davantage de requêtes réseau. Il faut viser un compromis entre taille des blocs, compression et cache.
Besoin d'un accompagnement SEO ?
Un JavaScript trop lourd plombe vos performances et votre visibilité ? Faites analyser votre site et identifiez les blocs à fractionner en priorité.