Gérer une large codebase à grande vitesse : Turborepo en production
Quand un monorepo grandit jusqu'à des dizaines de packages et que le CI prend 20 minutes, quelque chose doit changer. Le graphe de tâches et le cache distant de Turborepo ont drastiquement réduit nos temps de pipeline — voici la configuration exacte que nous utilisons et les pièges que nous avons contournés.
À mesure que les projets JavaScript grandissent, gérer plusieurs applications et packages partagés devient de plus en plus complexe. Les temps de build ralentissent, la duplication de code s'installe, et la productivité des développeurs en pâtit. Turborepo résout ces problèmes en proposant un système de build haute performance conçu spécifiquement pour les monorepos. Dans ce guide, je vous accompagne pas à pas dans la mise en place d'un workspace Turborepo prêt pour la production.
Qu'est-ce que Turborepo ?
Turborepo est un système de build qui optimise les monorepos JavaScript et TypeScript grâce à la mise en cache intelligente et à la parallélisation des tâches. Au lieu de tout reconstruire à chaque changement, Turborepo détecte ce qui a changé et ne reconstruit que le nécessaire.
Les principaux avantages sont :
- Ne jamais refaire le même travail deux fois : Turborepo met en cache les sorties des tâches et les restaure lorsque les entrées n'ont pas changé.
- Parallélisation maximale : Les tâches s'exécutent simultanément sur tous les cœurs CPU disponibles.
- Cache distant : Partagez les artefacts mis en cache avec votre équipe et vos pipelines CI.
- Adoption progressive : Fonctionne avec vos scripts package.json existants et supporte npm, yarn, pnpm et bun.
Installation
Installez Turborepo globalement pour pouvoir exécuter des commandes depuis n'importe quel endroit dans votre dépôt :
npm install turbo --global
Ou ajoutez-le comme dépendance de développement dans votre package.json racine :
npm install turbo --save-dev
Structure du dépôt
Un workspace Turborepo suit une organisation standard de monorepo avec deux répertoires principaux :
my-turborepo/ ├── apps/ │ ├── web/ # Application Next.js │ │ ├── package.json │ │ └── src/ │ └── api/ # Service backend │ ├── package.json │ └── src/ ├── packages/ │ ├── ui/ # Bibliothèque de composants partagés │ │ ├── package.json │ │ └── src/ │ ├── utils/ # Utilitaires partagés │ │ ├── package.json │ │ └── src/ │ └── typescript-config/ # Configuration TypeScript partagée │ └── package.json ├── package.json # Configuration du workspace racine ├── turbo.json # Configuration Turborepo └── pnpm-workspace.yaml # Définition du workspace (pnpm)
- apps/ contient les applications et services déployables.
- packages/ contient les bibliothèques partagées, les utilitaires et les configurations.
Configuration du workspace
Configurez d'abord votre gestionnaire de packages pour qu'il reconnaisse la structure du workspace.
Pour pnpm (pnpm-workspace.yaml)
packages:
- "apps/*"
- "packages/*"
Pour npm/yarn (package.json)
{
"name": "my-turborepo",
"private": true,
"workspaces": [
"apps/*",
"packages/*"
],
"devDependencies": {
"turbo": "^2.0.0"
},
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"lint": "turbo run lint",
"test": "turbo run test"
}
}
Configuration de Turborepo
Le fichier turbo.json définit comment les tâches s'exécutent dans votre workspace. C'est ici que vous configurez les dépendances entre tâches, le comportement du cache et les sorties.
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"globalEnv": ["NODE_ENV"],
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": ["^build"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
}
}
}
Explication des options de configuration
- globalDependencies : Fichiers qui affectent toutes les tâches. Toute modification de ces fichiers invalide l'intégralité du cache.
- globalEnv : Variables d'environnement qui affectent les hashs de toutes les tâches.
- dependsOn : Tâches qui doivent se terminer avant que cette tâche s'exécute. Le préfixe
^signifie « exécuter cette tâche dans les dépendances en premier ». - outputs : Fichiers et répertoires à mettre en cache après la réussite de la tâche.
- cache : Mettre à false pour les tâches qui ne doivent jamais être mises en cache (comme les serveurs de développement).
- persistent : Marque les tâches longues qui ne se terminent pas (comme le mode watch ou les serveurs de développement).
Comprendre les dépendances de tâches
La configuration dependsOn contrôle l'ordre d'exécution des tâches. Il existe trois modèles :
Dépendances en premier (^)
{
"tasks": {
"build": {
"dependsOn": ["^build"]
}
}
}
Le caret (^) signifie : avant de construire un package, construisez d'abord tous les packages dont il dépend. Si web dépend de ui, Turborepo construit ui avant web.
Dépendances dans le même package
{
"tasks": {
"test": {
"dependsOn": ["build"]
}
}
}
Sans le caret, la dépendance est au sein du même package. Les tests ne s'exécutent qu'après la fin du build de ce package.
Tâches de packages spécifiques
{
"tasks": {
"deploy": {
"dependsOn": ["web#build", "api#build"]
}
}
}
Vous pouvez référencer des tâches de packages spécifiques avec la syntaxe package#task.
Créer des packages internes
Les packages internes permettent de partager du code dans votre monorepo. Voici comment créer une bibliothèque de composants UI partagée.
Structure du package
packages/ui/
├── package.json
├── tsconfig.json
└── src/
├── button.tsx
├── card.tsx
└── index.ts
Configuration du package (packages/ui/package.json)
{
"name": "@repo/ui",
"version": "0.0.0",
"private": true,
"exports": {
"./button": "./src/button.tsx",
"./card": "./src/card.tsx"
},
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"lint": "eslint src/"
},
"devDependencies": {
"@repo/typescript-config": "workspace:*",
"typescript": "^5.0.0"
}
}
Utilisation du package
Ajoutez le package interne comme dépendance dans votre application :
{
"name": "web",
"dependencies": {
"@repo/ui": "workspace:*"
}
}
Puis importez les composants directement :
import { Button } from "@repo/ui/button";
import { Card } from "@repo/ui/card";
Mise en cache
La mise en cache est le super-pouvoir de Turborepo. Lorsqu'une tâche est exécutée, Turborepo crée un hash à partir des entrées de la tâche. Si le hash correspond à une exécution précédente, il restaure les sorties mises en cache au lieu de réexécuter la tâche.
Ce qui est mis en cache
- Sorties de tâches : Fichiers spécifiés dans la configuration
outputs. - Journaux du terminal : Sortie console de l'exécution de la tâche.
Ce qui affecte le hash du cache
- Fichiers source suivis par Git
- Dépendances dans package.json et le lockfile
- Variables d'environnement spécifiées dans
envouglobalEnv - Configuration des tâches dans turbo.json
Cache distant
Partagez votre cache entre les machines et les pipelines CI en vous connectant au cache distant Vercel :
npx turbo login
npx turbo link
Une fois lié, les artefacts mis en cache sont téléchargés et partagés automatiquement. Votre pipeline CI peut restaurer des builds calculés localement, et vos collègues profitent du cache de chacun.
Contrôle du cache
turbo run build --force
Utilisez --force pour contourner la lecture du cache tout en continuant à écrire de nouvelles entrées dans le cache.
Exécuter des tâches
Turborepo propose des options puissantes pour exécuter des tâches dans votre workspace.
Exécuter tous les packages
turbo run build
Exécuter plusieurs tâches
turbo run build test lint
Filtrer par nom de package
turbo run build --filter=web
turbo run build --filter=@repo/ui
Filtrer par répertoire
turbo run build --filter="./apps/*"
turbo run lint --filter="./packages/ui"
Inclure les dépendances
turbo run build --filter=web...
Le suffixe ... inclut tous les packages dont web dépend.
Inclure les dépendants
turbo run build --filter=...ui
Le préfixe ... inclut tous les packages qui dépendent de ui.
Filtrer par modifications Git
turbo run build --filter=[HEAD^1]
turbo run build --filter=[main...feature-branch]
Intégration CI/CD
Turborepo s'intègre parfaitement avec les pipelines CI. Voici un exemple GitHub Actions :
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- run: pnpm install
- run: pnpm turbo run build test lint
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
Avec le cache distant activé, votre pipeline CI bénéficie des caches calculés localement, ce qui réduit considérablement les temps de build.
Checklist de production
- Activer le cache distant : Connectez-vous au cache distant Vercel ou hébergez-le vous-même pour partager le cache avec votre équipe.
- Configurer correctement les sorties : Des sorties manquantes signifient que les fichiers ne seront pas mis en cache, provoquant des erreurs lors des hits de cache.
- Utiliser les variables d'environnement avec discernement : N'incluez dans la configuration
envque les variables qui affectent réellement la sortie du build. - Configurer le cache CI : Transmettez
TURBO_TOKENetTURBO_TEAMà votre environnement CI. - Filtrer en CI : Utilisez
--filter=[HEAD^1]pour ne construire que ce qui a changé dans le dernier commit. - Désactiver le cache pour les tâches de développement : Mettez toujours
"cache": falsepour les serveurs de développement et les tâches en mode watch.
Conclusion
Turborepo transforme la gestion des monorepos d'un fardeau DevOps en un multiplicateur de productivité. Les points clés à retenir :
- La structure est importante : Séparez les apps et les packages pour des frontières claires.
- Configurez les dépendances : Utilisez le préfixe
^pour construire les dépendances avant les dépendants. - Mettez tout en cache : Définissez des sorties pour toutes les tâches qui produisent des fichiers.
- Activez le cache distant : Partagez les artefacts de build avec votre équipe et votre CI.
- Filtrez stratégiquement : Ne construisez que ce dont vous avez besoin pendant le développement et le CI.
Avec une bonne configuration, Turborepo peut réduire les temps de build de 80 % ou plus, permettant à votre équipe de se concentrer sur la livraison de fonctionnalités plutôt que d'attendre la fin des builds.
Écrit par

Tech Lead et Ingénieur Full Stack pilotant une équipe de 5 ingénieurs chez Fygurs (Paris, Remote) sur un SaaS cloud-native Azure. Diplômé de 1337 Coding School (42 Network / UM6P). Écrit sur l'architecture, l'infrastructure cloud et le leadership technique.