~3 min de lecture
Comment j'ai réduit de 25% la taille de mon bundle Angular
Tu utilises Zod pour valider tes données dans ton app Angular ? Tu pourrais embarquer des dizaines de fichiers de traduction sans le savoir. Voici comment j'ai fait passer mon bundle initial de plus d'1 MB à 750 KB.
Le contexte
Projet Angular 20 avec Nx, build esbuild. Au lancement du build : warning Angular — le bundle initial dépasse 1 MB. Ce seuil n'est pas anodin, c'est la limite au-delà de laquelle Angular considère que ton app met trop de temps à charger. Il fallait investiguer.
Étape 1 : Visualiser son bundle
Avant d'optimiser quoi que ce soit, il faut mesurer. Angular avec esbuild génère un fichier stats.json qu'on peut
exploiter :
nx build mon-app --statsJson
npx esbuild-visualizer --metadata dist/apps/mon-app/stats.json --open
Le visualizer affiche une treemap interactive où chaque rectangle représente un module, sa taille étant proportionnelle à son poids dans le bundle.
Étape 2 : L'anomalie Zod
En parcourant la treemap, un chunk attire l'attention : Zod v4 occupe une place disproportionnée. En zoomant, on découvre le coupable — des dizaines de fichiers de locales :
nl.js(néerlandais)pt.js(portugais)de.js(allemand)ko.js(coréen)- ... et bien d'autres
Notre app n'utilise qu'une seule langue. Tout ce poids est du bloat pur.
Étape 3 : La fausse piste du plugin esbuild
Première idée : créer un plugin esbuild pour exclure les locales non utilisées à la compilation. Sur le papier, c'est élégant.
En pratique ? Échec. Les incompatibilités de schéma entre la configuration Nx et Angular CLI rendent l'intégration d'un plugin custom particulièrement pénible. Après plusieurs heures de debug, on abandonne cette piste.
Étape 4 : La solution — Zod Mini
En fouillant la documentation de Zod v4, on découvre zod/mini : une version allégée de la librairie qui exclut les
locales et certaines fonctionnalités avancées rarement utilisées.
Le changement est trivial :
// Avant
import {z} from 'zod';
// Après
import {z} from 'zod/mini';
L'API reste identique pour les cas d'usage courants. Si tu utilises uniquement z.object(), z.string(), z.number()
et les validations basiques, zod/mini couvre tes besoins.
Le résultat
Avant : un chunk massif contenant le core de Zod + des dizaines de fichiers de traduction. Bundle initial au-dessus d'1 MB.
Après : uniquement mini + core + une seule locale. Bundle initial : 750 KB.
Rien que ce changement a suffi à repasser sous le seuil d'Angular. 25% de gagné en modifiant une ligne d'import.
Bonus : Automatiser l'analyse de bundle
Pour éviter de taper ces commandes à chaque fois, tu peux créer une tâche dédiée dans ton workspace.
Avec Nx (project.json)
Ajoute cette target dans ton fichier project.json :
{
"targets": {
"analyze": {
"executor": "nx:run-commands",
"options": {
"commands": [
"nx build eak --statsJson",
"npx esbuild-visualizer --metadata dist/eak/stats.json --open"
],
"parallel": false
}
}
}
}
Puis lance l'analyse avec :
nx run mon-app:analyze
Avec Angular CLI
Si tu utilises Angular CLI sans Nx, ajoute ce script dans ton package.json :
{
"scripts": {
"analyze": "ng build --stats-json && npx esbuild-visualizer --metadata dist/stats.json --open"
}
}
Puis lance avec :
npm run analyze
# ou
pnpm run analyze
Ce qu'il faut retenir
Toujours mesurer avant d'optimiser. Sans le visualizer, on n'aurait jamais identifié ce problème. Le build passait, l'app fonctionnait — mais on embarquait du poids mort.
Les librairies de validation cachent souvent du bloat. Zod n'est pas un cas isolé. Yup, Joi et d'autres peuvent inclure des fonctionnalités ou locales que tu n'utilises pas.
Chercher la version "mini" avant de bricoler. Beaucoup de librairies proposent des builds allégés (lodash-es,
date-fns avec tree-shaking, zod/mini...). C'est souvent la solution la plus simple et la plus maintenable.