Une agence qui maintient plusieurs extensions WordPress front-heavy dans un même dépôt monorepo (un paquet partagé de composants, un plugin de blocs personnalisés, une extension e-commerce maison) finit par constater que chaque exécution de npm run build recompile l’ensemble des paquets, y compris ceux qui n’ont subi aucune modification depuis le dernier build. Sur six paquets front dans le même dépôt, cette recompilation systématique gaspille un temps de build proportionnel à la taille totale du monorepo, pas à celle du changement réellement effectué.
Turborepo répond à ce problème par deux mécanismes combinés : un cache de build par tâche, qui reconnaît qu’un paquet inchangé n’a pas besoin d’être recompilé, et une parallélisation automatique basée sur le graphe de dépendances entre paquets.
Structure d’un monorepo de plugins
monorepo-plugins/
├── packages/
│ ├── ui-composants/ # composants React partagés
│ ├── plugin-blocs/ # extension de blocs Gutenberg
│ └── plugin-ecommerce/ # extension e-commerce maison
├── turbo.json
└── package.json
Configurer les tâches dans turbo.json

{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"lint": {
"outputs": []
},
"test": {
"dependsOn": ["build"],
"outputs": []
}
}
}
La clé dependsOn: ["^build"] indique que le build d’un paquet dépend d’abord du build de ses dépendances internes au monorepo (le symbole ^ signifie « les paquets dont celui-ci dépend »). Turborepo construit ainsi un graphe d’exécution et lance en parallèle tout ce qui peut l’être, tout en respectant l’ordre réel des dépendances.
Le cache en action
npx turbo run build
# Premier lancement
• packages/ui-composants: build (cache miss) — 12.4s
• packages/plugin-blocs: build (cache miss) — 8.1s
• packages/plugin-ecommerce: build (cache miss) — 15.2s
# Second lancement, sans aucune modification
npx turbo run build
• packages/ui-composants: build (cache hit) — 0.1s
• packages/plugin-blocs: build (cache hit) — 0.1s
• packages/plugin-ecommerce: build (cache hit) — 0.1s
Ce cache repose sur une empreinte calculée à partir du contenu réel des fichiers sources de chaque paquet, pas seulement de leur date de modification : un fichier resauvegardé sans changement de contenu ne déclenche pas de nouveau build.
Modifier un seul paquet
Si seul plugin-blocs est modifié, Turborepo ne recompile que ce paquet et, si nécessaire, les paquets qui en dépendent (aucun ici, puisque c’est une feuille du graphe) :
npx turbo run build --filter=plugin-blocs...
L’option --filter permet de cibler explicitement un paquet et ses dépendants, utile en CI pour ne rebuilder que ce qui a réellement changé sur une pull request donnée.
Le cache distant, une étape supplémentaire
Par défaut, ce cache reste local à la machine. Turborepo propose aussi un cache distant, hébergé sur Vercel ou sur une infrastructure propre via un serveur de cache compatible, qui permet de partager les résultats de build entre les postes de l’équipe et les runners CI : un build déjà effectué par un collègue sur une branche commune n’a pas besoin d’être répété sur le runner CI qui teste ensuite la même pull request.
Turborepo face à un monorepo sans outillage dédié
| Critère | npm run build classique | Turborepo |
|---|---|---|
| Paquets inchangés | Recompilés à chaque fois | Ignorés grâce au cache |
| Parallélisation | Séquentielle par défaut | Automatique selon le graphe |
| Cache partagé entre postes | Inexistant | Possible via cache distant |
Sur un monorepo de deux ou trois paquets, la complexité de Turborepo dépasse largement le gain obtenu. À partir d’une demi-douzaine de paquets front interdépendants, la bascule devient nettement rentable.
En résumé
Pour un monorepo de plusieurs extensions WordPress partageant des dépendances front, Turborepo transforme un temps de build proportionnel à la taille totale du dépôt en un temps proportionnel à l’ampleur réelle du changement effectué. Le gain se mesure autant en confort quotidien pour l’équipe qu’en minutes CI économisées sur chaque pull request.