Taille du bundle : le régime pour votre JavaScript
JavaScript est la ressource la plus chère du Web. Un guide technique sur le Tree Shaking, le Code Splitting et l'utilisation de Partytown pour survivre à l'apocalypse des scripts tiers.
“Le site est rapide sur mon MacBook Pro.” C’est la phrase la plus dangereuse de l’ingénierie frontend. Votre MacBook Pro dispose d’une puce M3 Max. Il analyse 1 Mo de JavaScript en 50 ms. Votre utilisateur possède un Samsung Galaxy A15 à 200 €. Il analyse ce même 1 Mo en 2,5 secondes. Pendant ces 2,5 secondes, le thread principal est gelé. L’utilisateur clique sur “Ajouter au panier”. Rien ne se passe. Ils partent.
En 2025, la vitesse du réseau (4G/5G) constitue rarement un goulot d’étranglement pour le commerce électronique. Le processeur est le goulot d’étranglement. Et la métrique qui suit cela est Interaction avec Next Paint (INP). Pour corriger INP, vous devez réduire la charge utile JavaScript.
Chez Maison Code Paris, nous appliquons des budgets stricts : <100 Ko de charge initiale.
Pourquoi Maison Code en parle
Chez Maison Code Paris, nous agissons comme la conscience architecturale de nos clients. Nous héritons souvent de stacks “modernes” construites sans compréhension fondamentale de l’échelle.
Nous abordons ce sujet car il représente un point de pivot critique dans la maturité de l’ingénierie. Une mise en œuvre correcte différencie un MVP fragile d’une plateforme résiliente de niveau entreprise.
1. Le coût des importations : le tremblement des arbres
Tree Shaking (Dead Code Elimination) est le processus de suppression des exportations inutilisées de votre bundle. Mais cela ne fonctionne pas par magie. Vous devez écrire du code “Shakeable”.
Le piège du fichier baril
Les développeurs adorent les “Barrel Files” (index.ts qui exporte tout).
Ils détruisent Tree Shaking.
Mauvais modèle :
// composants/index.ts
exporter * depuis './Button' ;
exporter * depuis './Carousel' ; // Composant géant de 50 Ko
exporter * depuis './Table';
// App.tsx
importer { Button } depuis './components' ;
Dans de nombreuses configurations de bundle (en particulier les anciens Webpack), l’importation de « Button » inclura également « Carousel » dans le bundle, en raison des limitations de détection des effets secondaires.
Correction : importations directes ou configuration minutieuse de sideEffects : false dans package.json.
Le piège de la bibliothèque (Lodash)
import { map } from 'lodash'; récupère l’intégralité de la bibliothèque de 70 Ko.
Utilisez lodash-es ou des importations spécifiques : importer la carte depuis 'lodash/map' ;.
Mieux encore, utilisez des méthodes de tableau natives. [].map() coûte 0 octet.
2. Fractionnement de code : itinéraires de chargement paresseux
Pourquoi envoyer le code « Admin Dashboard » à un client qui vient d’acheter une chemise ? Nous utilisons le fractionnement de code basé sur l’itinéraire.
Dans Next.js (App Router), cela se produit automatiquement pour les fichiers page.tsx.
Dans Vite/React Router, vous devez utiliser lazy().
importer { paresseux, Suspense } depuis 'react' ;
// Cette importation dynamique crée un morceau séparé (par exemple, Settings.chunk.js)
const SettingsPage = lazy(() => import('./pages/Settings'));
fonction App() {
retour (
<Itinéraires>
<Route path="/" element={<Accueil />} />
<Route path="/settings" element={
<Suspense repli={<Spinner />}>
<Page Paramètres />
</Suspense>
} />
</Itinéraires>
);
}
Fractionnement au niveau des composants
Votre « Visionneuse de modèles 3D » est-elle lourde ? Ne le chargez pas au chargement de la page. Chargez-le sur interaction.
const ModelViewer = Dynamic(() => import('./ModelViewer'), { ssr: false });
fonction PageProduit() {
const [show3D, setShow3D] = useState(false);
retour (
<>
<button onClick={() => setShow3D(true)}>Vue en 3D</button>
{show3D && <ModelViewer />}
</>
);
}
Le JS lourd n’est téléchargé que lorsque l’utilisateur le demande réellement.
3. Visualiser le ballonnement
Vous ne pouvez pas réparer ce que vous ne pouvez pas voir.
Nous utilisons @next/bundle-analyzer (ou rollup-plugin-visualizer).
Exécutez-le avant chaque déploiement.
Vous trouverez des horreurs :
- Three.js dans le bundle de la page d’accueil ?
- Moment.js paramètres régionaux ? (Utilisez l’API
date-fnsouIntl). - Faker.js en production ? (Ce devrait être une devDependency).
Nous réduisons généralement la taille du bundle de 30 % simplement en supprimant les dépendances inutilisées trouvées dans le visualiseur.
4. Scripts tiers : la solution « Partytown »
Vous avez optimisé le code de votre application à 50 Ko. Parfait. Ensuite, l’équipe marketing ajoute GTM (Google Tag Manager). GTM injecte : *Pixel Facebook (40 Ko)
- Pixels TikTok (50 Ko)
- Hotjar (70 Ko)
- Klaviyo (40 Ko)
- Gorgias (200 Ko)
Soudain, votre fil de discussion principal est bloqué par 500 Ko de scripts marketing. La solution est l’architecture hors fil principal.
Nous utilisons Partytown.
Il exécute des scripts tiers dans un Web Worker.
Il proxy l’accès au DOM (par exemple, document.cookie) du Worker au Main Thread via XHR synchrone (Atomic Wait).
// layout.tsx (Suivant.js)
importer { Validation } depuis './Partytown' ;
<Tête>
<Partytown debug={true} forward={['dataLayer.push']} />
</Tête>
<Script
src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXX"
type="text/partytown" // Attribut magique
/>
Résultat : Le pixel Facebook s’exécute sur un fil d’arrière-plan. Il calcule les données de suivi sans figer votre bouton « Ajouter au panier ». L’INP s’améliore considérablement.
5. Formats modernes : expédition sans code
Les polyfills sont obsolètes
Supportez-vous Internet Explorer 11 ? Non.
Arrêtez d’envoyer des polyfills pour Promise, Map, Set, fetch.
Définissez votre cible browserslist sur defaults, pas IE 11.
Cela supprime environ 30 Ko de fichiers indésirables hérités.
Compression Brotli
Gzip est bon. Brotli est meilleur. Brotli (br) compresse JavaScript environ 20 % mieux que Gzip. Assurez-vous que Brotli est activé sur votre CDN (CloudFront/Vercel).
6. Optimisation d’image : la charge utile cachée
JavaScript est le goulot d’étranglement du processeur, mais les images sont le goulot d’étranglement de la bande passante. Si vous chargez un PNG de 2 Mo sur une connexion 4G, le téléchargement JS est retardé. Stratégie :
- Format : utilisez AVIF. Il est 30 % plus petit que WebP.
- Lazy Loading :
<img chargement="lazy">pour tout ce qui se trouve en dessous de la ligne de flottaison. - Dimensions : définissez toujours la « largeur » et la « hauteur » pour éviter les décalages de mise en page (CLS).
- CDN : utilisez Cloudinary ou Imgix pour redimensionner à la volée.
image.jpg?w=400&q=auto
7. Stratégie de chargement des polices
Les polices bloquent le rendu. Si vos fichiers OTF font 100 Ko, le texte est invisible (FOIT) pendant 2 secondes. Correction :
- Auto-hébergement : n’utilisez pas Google Fonts. La recherche DNS vous surprend.
- Sous-ensemble : supprimez les glyphes que vous n’utilisez pas (par exemple, les caractères cyrilliques).
- Échange d’affichage :
font-display: swap;. Affichez immédiatement la police de secours. - Préchargement :
<link rel="preload" href="/font.woff2" as="font">pour la police de titre uniquement.
8. Le DX « Coût d’importation »
Les développeurs sont paresseux. S’ils peuvent importer une bibliothèque, ils le feront. Installez l’extension Import Cost dans VS Code. Il affiche la taille de l’importation en ligne au fur et à mesure que vous tapez.
importer { format } depuis 'date-fns' ; // 14 Ko (Gzippé)
Cette boucle de rétroaction instantanée incite les développeurs à réfléchir à deux fois avant d’ajouter une dépendance.
8. L’avenir : possibilité de reprise (Qwik)
Le défaut fondamental de React est l’hydratation.
L’hydratation signifie : “Téléchargez le HTML. Ensuite, téléchargez le JS. Ensuite, exécutez le JS pour attacher les écouteurs d’événements.”
C’est un travail en double.
Des frameworks comme Qwik introduisent la Resumability.
Il n’y a pas d’hydratation.
L’écouteur d’événements est sérialisé dans le code HTML : <button on:click="./chunk.js#handleClick">.
Le JS pour le gestionnaire de clics est uniquement téléchargé lorsque l’utilisateur clique réellement.
S’ils ne cliquent jamais, vous téléchargez 0 Ko de JS.
C’est l’idéal “O(1) JavaScript”. Nous suivons cela de près pour 2026.
9. Composants du serveur React (RSC)
Le routeur d’application Next.js utilise RSC.
RSC permet de conserver les dépendances sur le serveur.
Avant RSC :
import { format } from 'date-fns' -> Le bundle client augmente de 20 Ko.
Après RSC :
import { format } from 'date-fns' -> S’exécute sur le serveur. Rend le HTML. Le bundle client augmente de 0 Ko.
Stratégie : déplacez tous les traitements lourds de formatage, de récupération de données et de démarques vers les composants du serveur.
Conservez les composants clients uniquement pour l’interactivité (useState, useEffect).
Les « nœuds feuilles » doivent être des composants clients. Les « nœuds de conteneur » doivent être des composants du serveur.
9. La règle budgétaire des 100 Ko
Nous avons une règle stricte : Vous ne pouvez pas fusionner un PR qui pousse le bundle initial à plus de 100 Ko.
Nous appliquons cela via CI.
La vérification de bundlesize échoue :
“Erreur : le paquet principal fait 105 Ko. La limite est de 100 Ko.” Cela force une conversation. “Avons-nous vraiment besoin de cette bibliothèque ? Pouvons-nous la charger paresseusement ?” Si vous ne l’appliquez pas, le bundle grandira à l’infini. Chaque KB doit se battre pour sa vie.
10. Conclusion
La performance n’est pas un « agréable à avoir ». Ce sont des revenus. Amazon a constaté que 100 ms de latence leur coûtaient 1 % de leurs ventes. Latence JavaScript IS gonflée. Traitez votre budget de taille de forfait comme un budget financier. Si vous le dépassez, vous devez le « rembourser » en supprimant le code.
Votre site est-il lourd ?
Votre score de performance Lighthouse indique-t-il « Réduire le code JavaScript inutilisé » ?
Auditer mon forfait. Découvrez Core Web Vitals et Edge Computing.
La performance n’est pas un « agréable à avoir ». Ce sont des revenus. Amazon a constaté que 100 ms de latence leur coûtaient 1 % de leurs ventes. Latence JavaScript IS gonflée. Traitez votre budget de taille de forfait comme un budget financier. Si vous le dépassez, vous devez le « rembourser » en supprimant le code.
Votre site est-il lourd ?
Votre score de performance Lighthouse indique-t-il « Réduire le code JavaScript inutilisé » ?