title: "Structurer un monorepo Next.js avec Turborepo et pnpm workspaces en 2026" description: "Guide pratique pour mettre en place un monorepo Next.js en 2026 avec Turborepo 2.x, pnpm workspaces et un cache partagé entre équipes." date: "2026-06-11" category: "Ingénierie" readingTime: "8 min" author: "Oliwer Fortin, Tech Lead chez Kreio"
Gérer plusieurs applications Next.js dans un seul dépôt est devenu la norme pour les équipes qui veulent partager du code sans dupliquer leur configuration. Avec Turborepo 2.x et pnpm workspaces, on dispose aujourd'hui d'une solution mature, rapide et bien documentée pour structurer un monorepo Next.js en 2026.
Pourquoi adopter un monorepo pour ses projets Next.js
Un dépôt multi-projets classique, avec plusieurs repos Git distincts, pose rapidement des problèmes de cohérence : versions de dépendances qui divergent, composants UI copiés d'un repo à l'autre, configurations TypeScript dupliquées à chaque nouveau projet.
Un monorepo regroupe toutes les applications et les packages partagés dans un seul dépôt Git. Les bénéfices concrets sont mesurables : les packages internes deviennent des dépendances de premier rang sans passer par npm, un changement dans un composant @repo/ui se répercute immédiatement sur toutes les applications qui en dépendent, et la CI peut détecter précisément quels packages sont affectés par un commit pour ne rebuilder que ceux-là.
Cela dit, un monorepo introduit une complexité de configuration initiale. Pour un projet solo ou une stack très simple, le surcoût ne se justifie pas. Le seuil de rentabilité se situe généralement à partir de deux applications partageant des composants ou une logique métier.
La base : pnpm workspaces
pnpm est le gestionnaire de paquets recommandé pour les monorepos en 2026. Son store centralisé de dépendances réduit l'espace disque utilisé d'environ 40 % par rapport à npm, grâce à un mécanisme de liens symboliques plutôt que de copies intégrales. La documentation officielle de pnpm détaille la configuration des workspaces.
La configuration minimale tient en deux fichiers à la racine du dépôt.
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"
// package.json (racine)
{
"name": "my-monorepo",
"private": true,
"scripts": {
"build": "turbo build",
"dev": "turbo dev",
"lint": "turbo lint"
},
"devDependencies": {
"turbo": "^2.0.0"
}
}
Le dossier apps/ accueille les applications (par exemple apps/web et apps/admin) et packages/ contient les packages partagés : packages/ui, packages/config-ts, packages/utils.
Pour référencer un package interne depuis une application, on utilise le protocole workspace:* :
// apps/web/package.json
{
"name": "web",
"dependencies": {
"@repo/ui": "workspace:*"
}
}
pnpm résout automatiquement ces dépendances localement, sans passer par le registre npm. La version installée correspond toujours à l'état courant du package dans le monorepo, ce qui évite les désynchronisations entre applications.
Configurer Turborepo 2.x
Turborepo orchestre l'exécution des tâches en tenant compte du graphe de dépendances entre packages. Depuis la version 2.0, la clé pipeline a disparu. Les tâches sont déclarées directement sous tasks dans turbo.json :
// turbo.json
{
"$schema": "https://turborepo.dev/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", "dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {},
"type-check": {
"dependsOn": ["^build"]
}
}
}
La notation ^build signifie : « avant de builder ce package, builder d'abord toutes ses dépendances internes ». C'est le mécanisme central de Turborepo. Sans cette directive, une application qui importe @repo/ui pourrait tenter de compiler avant que @repo/ui soit prête, ce qui provoque des erreurs de types ou des imports manquants.
Structurer les packages internes
La vraie valeur d'un monorepo réside dans les packages partagés. Voici les trois types les plus courants dans un projet Next.js professionnel.
| Package | Rôle | Contenu typique |
|---|---|---|
@repo/ui | Composants React réutilisables | Button, Modal, Card, Input |
@repo/config-ts | Configuration TypeScript commune | tsconfig.base.json |
@repo/utils | Fonctions utilitaires partagées | formatDate, slugify, cn() |
Pour les composants UI, la stratégie dite « just-in-time » est la plus simple à maintenir : le package expose directement ses fichiers TypeScript, et Next.js les compile au moment du build de l'application via transpilePackages :
// apps/web/next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
transpilePackages: ["@repo/ui"],
};
export default nextConfig;
Cette approche évite une étape de build intermédiaire sur le package UI. Le code source est compilé une seule fois, dans le contexte de l'application qui le consomme, avec les optimisations de Next.js (tree-shaking, code splitting) pleinement actives.
Pour les packages qui nécessitent un build propre, par exemple un package destiné à être publié sur npm ou contenant du CSS compilé, il faut ajouter un script build dans leur package.json et exposer les sorties via le champ exports.
Cache local et cache distant
Le système de cache de Turborepo repose sur une empreinte. Pour chaque tâche, Turborepo calcule un hash à partir des fichiers sources, du contenu de package.json, des variables d'environnement déclarées dans turbo.json et de la configuration de la tâche. Si ce hash correspond à une entrée existante, Turborepo restaure les artefacts en quelques millisecondes.
Le gain de temps effectif dépend du taux de cache hit . La durée d'un build après mise en cache suit la relation :
Avec très proche de zéro, un taux réduit la durée effective de build de 80 % sur les runs suivants. En pratique, les équipes rapportent des taux entre 0,6 et 0,9 selon la fréquence des changements.
Le cache local (stocké dans .turbo/) est efficace en développement individuel. Le cache distant étend ce mécanisme à toute l'équipe et aux runners CI : un build lancé en local peut être restauré directement sur GitHub Actions, sans aucun recalcul. La configuration se fait en deux commandes :
# Liaison au cache distant Vercel (plan gratuit disponible)
npx turbo login
npx turbo link
Des retours publiés en 2026 font état de réductions de 30 % à 62 % sur les durées de CI selon la taille du monorepo. La documentation officielle Turborepo sur le cache distant décrit comment configurer un backend alternatif sur S3 ou Cloudflare R2 pour les équipes qui ne souhaitent pas passer par Vercel.
Ce qu'on en retient
Turborepo et pnpm workspaces forment la combinaison la plus accessible pour structurer un monorepo Next.js en 2026. L'investissement de configuration initial est amorti dès qu'une deuxième application consomme un package partagé, et le cache distant change concrètement la vélocité des équipes en CI.
Les points clés à retenir : déclarer les outputs avec précision, car un cache mal configuré est pire qu'un cache inexistant ; utiliser workspace:* pour les dépendances internes afin que pnpm garantisse toujours la version locale ; activer le cache distant dès que l'équipe dépasse une personne ; et préférer les packages « just-in-time » pour les composants UI afin d'éviter des étapes de build inutiles.
Pour approfondir, la documentation Turborepo pour Next.js et le guide officiel Next.js sur les monorepos sont les références à conserver.