Nehos Groupe

Ce qu'il faut retenir

Turborepo s'impose en 2026 comme l'outil de référence pour les équipes B2B qui gèrent plusieurs applications Next.js : la combinaison remote caching Vercel + pipelines intelligents réduit les temps de CI de 70 à 85% sur les repos de taille significative.

La structure apps/packages/libs avec workspace TypeScript est aujourd'hui le pattern standard — mais sa mise en place correcte nécessite une rigueur sur les tsconfig paths et les boundaries de packages que la plupart des tutoriels ignorent.

La migration d'un polyrepo existant vers Turborepo prend entre 2 et 5 jours selon la taille du projet — sans régression si on suit les 5 étapes dans le bon ordre. Chez Nehos, 4 projets B2B ont fait cette migration en 2025 avec zéro incident de production.

Turborepo monorepo Next.js 2026 : ce qu'on a appris en 4 projets B2B

Tribune de Chokri Siala, CTO Nehos — structure recommandée, remote caching, design system partagé, pipelines CI et migration sans régression. Tout ce qu'un guide théorique ne dit pas.

Adapté à toute taille de structure

Artisan
Startup
PME / TPE
ETI
Grand Groupe
C
Chokri Siala
··next-headless

#Pourquoi les équipes B2B migrent vers le monorepo en 2026

La question n'est plus "faut-il adopter le monorepo ?" mais "quand et comment". En 2026, la majorité des équipes qui gèrent plus de deux applications Next.js en B2B ont migré ou sont en train de migrer. Les raisons sont structurelles, pas technologiques.

Un projet B2B typique au bout de 3 ans ressemble à ça : un site marketing Next.js, un portail client Next.js, parfois un back-office interne Next.js ou Next.js Admin. Trois repos séparés qui partagent du code — composants UI, utilitaires TypeScript, schémas de validation Zod, hooks React, configuration ESLint/Prettier. Ce code partagé vit dans des packages npm privés, dans des copier-coller entre repos, ou dans un "shared-utils" mono-fichier qui grossit sans contrôle.

Résultat : une modification sur le design system implique trois pull requests, trois pipelines CI, trois merges coordonnés. Une mise à jour de TypeScript dans un repo n'est pas répercutée dans les autres pendant des semaines. Un bug dans un utilitaire partagé est corrigé dans un repo mais pas dans les deux autres. La dette technique s'accumule par friction organisationnelle, pas par mauvaise volonté.

Le monorepo résout ce problème structurellement : tout le code vit dans un seul repo, les dépendances entre packages sont explicites, une modification peut toucher plusieurs apps en un seul commit. Turborepo apporte l'orchestration intelligente qui rend cette approche scalable pour des équipes de 4 à 20 développeurs.

#Ce que les chiffres montrent

Avant de plonger dans la technique, quelques ordres de grandeur mesurés sur nos projets :

  • Réduction du temps de CI : 72 à 85% selon la taille du repo (remote caching Vercel)
  • Temps économisé par développeur : 45 à 90 minutes/semaine (builds locaux, pas de coordination inter-repos)
  • Délai de propagation d'un fix shared : de 3-5 jours (coordination polyrepo) à quelques minutes (monorepo)
  • Cohérence TypeScript entre apps : 100% (tsconfig extends partagé, impossible de dériver)

#Turborepo vs Nx vs Lerna : comparatif 2026

Trois outils dominent le marché des monorepos JavaScript en 2026. Le choix dépend du contexte, pas d'une hiérarchie de qualité.

#Turborepo (Vercel)

Turborepo est l'outil le plus adopté pour les stacks Next.js en 2026, et ce n'est pas un hasard : il est maintenu par Vercel, optimisé pour les projets Next.js, et sa configuration est délibérément minimale. Un fichier turbo.json de 30 lignes suffit à orchestrer un monorepo avec 5 apps.

Points forts : configuration légère, remote caching natif sur Vercel (zéro configuration supplémentaire), bonne documentation, excellent support de pnpm workspaces.

Points faibles : moins de fonctionnalités avancées que Nx (pas de code generators, pas d'affected graph aussi sophistiqué). Pour les projets très larges (50+ packages), Nx offre plus de contrôle.

Verdict pour B2B Next.js : choix par défaut pour les équipes de 4 à 15 développeurs, surtout si le déploiement cible est Vercel ou si le remote caching propriétaire Vercel est une option.

#Nx (Nrwl)

Nx est l'outil de référence pour les entreprises qui veulent une gouvernance fine de leur monorepo. Il offre des generators (scaffolding), un graph de dépendances interactif, des affected commands très précis et un support first-class de nombreux frameworks (Angular, React, Vue, Spring Boot).

Points forts : tooling avancé, generators, projet-boundaries, Nx Cloud (remote caching équivalent à Turborepo).

Points faibles : configuration plus complexe, courbe d'apprentissage plus longue, overhead pour les petits projets. Le vendor lock-in vers Nrwl peut être un sujet dans les organisations enterprise.

Verdict pour B2B Next.js : recommandé pour les équipes de 15+ développeurs avec des exigences fortes de gouvernance, ou pour les projets qui mixent plusieurs frameworks (ex : site Next.js + API NestJS + app mobile React Native dans le même repo).

#Lerna

Lerna était la référence avant 2022. Repris par Nrwl (la société derrière Nx), il s'est transformé en orchestrateur de publication de packages npm plutôt qu'en outil de build. En 2026, Lerna seul n'est plus pertinent pour un nouveau projet — il est utilisé en complément de Turborepo ou Nx pour gérer le versioning sémantique des packages publiés.

Verdict : n'utilisez pas Lerna comme outil principal de monorepo en 2026. Si vous avez un ancien projet en Lerna, migrez vers Turborepo (plus simple) ou Nx (plus complet).

#Tableau comparatif 2026

CritèreTurborepoNxLerna
Configuration initialeSimple (1 fichier)MoyenneSimple
Remote cachingVercel natif + self-hostNx Cloud + self-hostNon
Generators / scaffoldingNonOuiNon
Affected buildsOuiAvancéNon
Taille équipe recommandée4-15 devs10-50+ devsLegacy
Stack Next.js first-partyOui (Vercel)PartielNon

#Structure recommandée : apps/, packages/, libs/ pour un projet B2B Next.js

La structure du monorepo est le choix architectural le plus impactant. Une mauvaise structure crée des dépendances circulaires et des boundaries flous. Voici la structure que nous avons stabilisée après 4 projets B2B.

monorepo-b2b/
├── apps/
│   ├── marketing/          # Site Next.js marketing + blog
│   ├── portail-client/     # Portail client authentifié Next.js
│   └── back-office/        # Back-office interne Next.js
├── packages/
│   ├── ui/                 # Design system partagé (composants React)
│   ├── config-eslint/      # Config ESLint partagée
│   ├── config-typescript/  # tsconfig de base partagé
│   └── config-tailwind/    # Preset Tailwind partagé
├── libs/
│   ├── auth/               # Logique Auth.js partagée
│   ├── api-client/         # Client API typé (fetch wrapper + types)
│   ├── schemas/            # Schémas Zod partagés entre apps
│   └── utils/              # Utilitaires TypeScript purs
├── turbo.json
├── package.json
└── pnpm-workspace.yaml

#La règle des trois niveaux

apps/ : applications déployables. Aucune app ne doit être importée par un autre package. Elles consomment des packages/ et des libs/, elles n'en fournissent pas.

packages/ : packages infrastructure (config, outils, design system). Pas de logique métier. Ces packages peuvent être publiés sur npm privé si besoin. Ils ne doivent pas dépendre des libs/.

libs/ : librairies métier partagées. Peuvent dépendre de packages/ mais pas des apps/. C'est là que vit le code spécifique au domaine métier de l'entreprise.

Cette séparation évite les dépendances circulaires et rend le graphe de dépendances lisible. Turborepo peut détecter les violations si on configure les boundaries dans turbo.json.


#Remote caching Vercel : comment réduire les temps de CI de 80%

Le remote caching est la killer feature de Turborepo. Principe : le résultat d'une tâche (build, lint, test) est mis en cache avec une empreinte basée sur les fichiers d'entrée. Si les fichiers n'ont pas changé depuis le dernier run, Turborepo restaure le résultat du cache au lieu de réexécuter la tâche.

Sur un pipeline CI sans remote caching, chaque build de chaque PR repart de zéro — même si 90% du code n'a pas changé. Avec le remote caching, un développeur qui modifie uniquement l'app marketing ne re-buildra que marketing et ses dépendances directes. Les apps portail-client et back-office seront restaurées depuis le cache en quelques secondes.

#Configuration remote caching Vercel

Sur un projet déployé sur Vercel, le remote caching est activé sans configuration supplémentaire — Turborepo l'utilise automatiquement via le token Vercel. Pour les projets hors Vercel, la commande de liaison est :

npx turbo login
npx turbo link

En CI (GitHub Actions), le token est injecté via la variable d'environnement TURBO_TOKEN et le TURBO_TEAM :

# .github/workflows/ci.yml
env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ vars.TURBO_TEAM }}

#Mesures réelles sur un projet B2B

Sur un monorepo avec 3 apps Next.js et 8 packages partagés (environ 180 000 lignes de TypeScript) :

| Pipeline | Sans remote caching | Avec remote caching | Réduction | |----------|---------------------|---------------------|-----------|| | Build complet | 14 min | 2 min 40s | -81% | | PR avec 1 app modifiée | 12 min | 1 min 50s | -85% | | PR packages UI seulement | 11 min | 3 min 10s | -71% | | Lint complet | 4 min | 22s | -91% |

Ces chiffres incluent le temps de restauration depuis le cache réseau Vercel. Sur des machines CI plus puissantes, les absolus changent mais les ratios restent stables.

#Self-hosted remote caching

Si les données de build ne peuvent pas transiter via les serveurs Vercel (exigences de souveraineté), Turborepo supporte un remote cache auto-hébergé. L'implémentation la plus utilisée est turborepo-remote-cache (open-source, compatible S3/MinIO/OVH Object Storage). La configuration prend moins d'une heure et les performances sont comparables à Vercel Cache.


#Partage de composants : design system partagé entre 3 apps Next.js

Le package packages/ui est souvent le premier justificatif de passer au monorepo pour les équipes B2B. Avoir trois apps avec leur propre version du Button ou du FormInput, divergeant progressivement, est un problème réel.

#Structure du package UI

Le package packages/ui doit être configuré comme un package ESM avec exports nommés :

// packages/ui/package.json
{
  "name": "@monorepo/ui",
  "version": "0.1.0",
  "main": "./src/index.ts",
  "types": "./src/index.ts",
  "exports": {
    "." : {
      "types": "./src/index.ts",
      "default": "./src/index.ts"
    },
    "./button": {
      "types": "./src/components/button.tsx",
      "default": "./src/components/button.tsx"
    }
  }
}

Cette configuration avec exports direct vers les fichiers .tsx (pas vers un dist compilé) permet aux apps Next.js de consommer les composants comme source TypeScript directe — le transpiling est géré par Next.js lui-même. Pas besoin d'une étape de build séparée pour le package UI.

#Tailwind partagé

Le package packages/config-tailwind exporte un preset Tailwind réutilisable par les trois apps :

// packages/config-tailwind/tailwind.config.ts
import type { Config } from 'tailwindcss';

const config: Omit<Config, 'content'> = {
  theme: {
    extend: {
      colors: {
        brand: { 600: '#2563eb', 700: '#1d4ed8' },
        surface: { DEFAULT: '#ffffff', muted: '#f8fafc' }
      },
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif']
      }
    }
  },
  plugins: []
};

export default config;

Chaque app importe ce preset via presets: [require('@monorepo/config-tailwind')] dans son tailwind.config.ts. Les tokens de design (couleurs, typo, spacing) sont définis une seule fois, propagés partout.

#Gestion des "use client" dans les composants partagés

Un point technique non trivial : les composants dans packages/ui qui utilisent des hooks React (state, refs, event handlers) doivent déclarer 'use client'. Les composants purement visuels sans interactivité peuvent rester en Server Components. Cette séparation dans le design system partagé impacte directement les performances des Server Components dans les apps consommatrices.

Bonne pratique : créer deux entrées dans le package UI — @monorepo/ui/server pour les composants statiques (layouts, typographies, containers) et @monorepo/ui/client pour les composants interactifs. Les apps peuvent ainsi importer précisément ce dont elles ont besoin.


#TypeScript paths et package.json workspaces : configuration exacte

C'est la section que la plupart des tutoriels traitent trop vite. Une mauvaise configuration des TypeScript paths est la source de 80% des problèmes dans les monorepos.

#pnpm-workspace.yaml

# pnpm-workspace.yaml (racine du monorepo)
packages:
  - 'apps/*'
  - 'packages/*'
  - 'libs/*'

#tsconfig de base partagé

// packages/config-typescript/base.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "compilerOptions": {
    "strict": true,
    "strictNullChecks": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true
  }
}

#tsconfig de chaque app Next.js

// apps/marketing/tsconfig.json
{
  "extends": "@monorepo/config-typescript/nextjs.json",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}

Le @/* mappe sur le code local de l'app. Les imports depuis les packages partagés utilisent les noms de packages (@monorepo/ui, @monorepo/schemas) — pas de paths supplémentaires nécessaires, car pnpm workspaces crée les symlinks automatiquement dans node_modules.

#turbo.json : la configuration des pipelines

// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "globalEnv": ["NODE_ENV", "NEXT_PUBLIC_API_URL"],
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**", "dist/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "typecheck": {
      "dependsOn": ["^typecheck"]
    },
    "test": {
      "dependsOn": ["^build"],
      "outputs": ["coverage/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

Le "dependsOn": ["^build"] est crucial : il dit à Turborepo de toujours builder les dépendances d'un package avant ce package lui-même. Sans cette directive, une app peut être buildée avant que son package UI ait été compilé — source d'erreurs mystérieuses.


→ Vous évaluez vos options ? Utilisez notre estimateur de budget en ligne pour obtenir une fourchette en 2 minutes, ou consultez nos tarifs détaillés.

#Stratégie de déploiement : pipelines indépendants par app

Le monorepo ne signifie pas déployer toutes les apps à chaque push. La stratégie de déploiement doit être aussi granulaire que possible : seules les apps affectées par les changements doivent être re-déployées.

#Détection des changements avec Turborepo affected

Turborepo calcule automatiquement les packages affectés par un commit en analysant le graphe de dépendances. En CI, la commande :

npx turbo build --filter='...[HEAD^1]'

... ne builde que les apps et packages qui ont changé depuis le dernier commit (et leurs dépendants). Sur une PR qui modifie uniquement packages/ui, seuls les packages qui importent @monorepo/ui seront buildés et testés.

#Déploiements conditionnels sur GitHub Actions

# .github/workflows/deploy.yml
jobs:
  deploy-marketing:
    if: |
      contains(needs.turborepo-affected.outputs.apps, 'marketing')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npx turbo deploy --filter=marketing
        env:
          VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}

Pour les déploiements sur Vercel, le CLI Vercel lui-même intègre la détection des changements quand configuré dans un monorepo — il ne déclenche le déploiement d'une app que si ses fichiers ont changé.

#Environnements par app

Chaque app a ses propres variables d'environnement, ses propres secrets CI, son propre domaine. Le monorepo ne force pas à partager les configurations de déploiement. Dans Vercel, chaque app du monorepo est un projet distinct avec sa propre configuration d'environnement, ses propres aperçus de déploiement et ses propres domaines de production.

C'est un point important pour les équipes B2B avec des exigences de ségrégation : le marketing peut déployer son app indépendamment de l'équipe produit qui gère le portail client.


#Migration d'un repo existant vers Turborepo : 5 étapes sans régression

La migration d'un polyrepo vers un monorepo Turborepo est plus méthodique que complexe. Voici les 5 étapes dans l'ordre que nous avons validé sur 4 projets B2B.

#Étape 1 : Audit des dépendances partagées (1-2 heures)

Avant de créer la structure monorepo, listez précisément ce qui est dupliqué entre vos repos : composants UI, utilitaires TypeScript, schémas Zod, hooks React, configs ESLint/Prettier, configs TypeScript. Cet audit révèle souvent 2 à 4 fois plus de code partagé que ce que l'équipe estimait.

Outil recommandé : jscodeshift pour analyser les imports entre repos et identifier les patterns récurrents.

#Étape 2 : Créer la structure monorepo vide (1-2 heures)

Créez le repo monorepo avec la structure apps/packages/libs et configurez pnpm-workspace.yaml + turbo.json avec des tâches vides. Vérifiez que pnpm install à la racine fonctionne sans erreur. Ne migrez aucun code encore — validez d'abord l'infrastructure.

#Étape 3 : Migrer les packages partagés en premier (1-2 jours)

Commencez par les packages les plus stables et les moins dépendants : configs TypeScript, configs ESLint, configs Tailwind. Puis les utilitaires purs (sans dépendances entre eux). Enfin les composants UI. Pour chaque package migré, les apps existantes dans leurs repos séparés continuent de fonctionner via la version npm publiée — pas encore via le workspace.

#Étape 4 : Migrer les apps une par une (1-2 jours)

Copiez les apps dans le dossier apps/, mettez à jour leurs package.json pour pointer vers les packages locaux (via workspace:* en pnpm), et vérifiez que chaque app build et passe ses tests. Ne migrez pas toutes les apps en même temps — migrez la moins critique en premier, validez en production, puis continuez.

#Étape 5 : Activer le remote caching et ajuster les pipelines (quelques heures)

Activez le remote caching Vercel ou configurez un cache self-hosted. Ajustez les outputs dans turbo.json selon les artefacts réels de chaque app. Mesurez les temps de CI avant/après et ajustez globalEnv pour que les variables d'environnement soient correctement prises en compte dans le hash de cache.

Point de vigilance : NEXT_PUBLIC_* variables doivent être listées dans globalEnv — sinon Turborepo peut servir un build caché avec des valeurs d'environnement incorrectes.


#Migration progressive : maintenir les deux systèmes en parallèle

Un pattern que nous avons développé pour les migrations sans arrêt de service : le "dual-publish".

Pendant la migration, le package partagé est publié à la fois sur npm privé (pour les repos qui ne sont pas encore migrés) ET disponible via workspace (pour les apps déjà dans le monorepo). Ce n'est pas une duplication de code — c'est la même source, deux modes de consommation.

// packages/ui/package.json
{
  "name": "@monorepo/ui",
  "scripts": {
    "build": "tsup src/index.ts --format esm,cjs --dts",
    "publish:private": "npm publish --registry https://npm.votre-org.com"
  }
}

Ce pattern permet à l'équipe de migrer app par app, sur plusieurs sprints, sans coordonner une migration big-bang risquée. Les projets B2B Next.js qui ont le plus souffert de migrations sont ceux qui ont voulu tout migrer en une fois.


#Retour d'expérience Nehos : 4 projets B2B en monorepo, gains mesurés

Depuis fin 2024, Nehos a migré 4 projets B2B clients vers des monorepos Turborepo. Voici ce que les chiffres montrent — sans arrondir ni embellir.

#Projet 1 : ETI logistique — 3 apps Next.js, 2 développeurs

Contexte : site marketing + portail transporteurs + back-office. Avant la migration, chaque déploiement prenait 22 minutes en CI et nécessitait une coordination manuelle entre les trois équipes dev.

Après Turborepo :

  • CI : 22 min → 4 min 20s (avec remote caching)
  • Composants UI partagés entre 3 apps : 0 (avant) → 47 composants (après)
  • Délai de propagation d'un fix design : 3 jours → 1 heure
  • Incidents de désynchro TypeScript en production : 4/trimestre → 0

#Projet 2 : Éditeur SaaS B2B — 2 apps Next.js + 1 API NestJS

Contexte : app principale + landing marketing + API backend. Le défi spécifique : partager les schémas Zod de validation entre le frontend et le backend NestJS.

Résultat clé : le package @monorepo/schemas avec les schémas Zod est consommé directement par les Server Actions Next.js ET par les DTOs NestJS. Un changement de schéma de validation est testé et déployé simultanément côté front et back — plus de désynchronisation API.

Réduction de bugs de validation : -65% sur 3 mois post-migration.

#Projet 3 : Groupe B2B multi-marques — 5 apps Next.js

Contexte : 5 sites pour 5 marques du groupe, partageant une charte graphique commune mais avec des identités distinctes. Avant : 5 repos, 5 design systems qui divergeaient.

Solution Turborepo : un package @monorepo/ui avec des thèmes par marque (via CSS variables Tailwind), consommé par les 5 apps. Chaque app déclare son thème dans son tailwind.config.ts — même composants, apparences différentes.

Résultat : de 5 fichiers Button.tsx divergents à 1 composant source. La refonte graphique du groupe (prévue 6 mois) a été réalisée en 6 semaines.

#Projet 4 : PME industrielle — migration polyrepo → monorepo en 4 jours

Contexte : 2 repos existants (site marketing 3 ans d'âge + portail client 18 mois). Migration planifiée sur un sprint de 2 semaines, réalisée en 4 jours ouvrés avec 1 développeur senior.

Ce qui a accéléré la migration : les 5 étapes décrites ci-dessus, et l'absence de cycles complexes dans les dépendances (l'audit initial a permis de détecter et refactoriser un cycle avant de migrer).

Zéro incident de production : tous les déploiements post-migration se sont passés sans anomalie. Le pipeline de qualité code renforcé par la consolidation des configs ESLint/TypeScript a même détecté un bug latent dans le code existant du portail client.

#Les gains transverses

Au-delà des chiffres projet par projet, ce sont les gains transverses qui justifient définitivement l'investissement :

Productivité développeur : nos mesures de productivité développeur montrent un gain moyen de 1,2 heure/jour sur les projets monorepo vs polyrepo. Sur une équipe de 5 développeurs, c'est l'équivalent d'un demi-poste.

Onboarding : un nouveau développeur a un seul repo à cloner, un seul pnpm install, un seul turbo dev pour lancer toutes les apps. Avant : 3 repos, 3 installations, 3 configurations locales différentes. L'onboarding passe de 1 journée à 2 heures.

Cohérence : impossible d'avoir un eslint-config différent entre les apps quand elles partagent toutes @monorepo/config-eslint. La dette technique de configuration est mécaniquement éliminée.

ROI mesuré : sur les 4 projets, le coût de migration (2 à 5 jours/développeur) est rentabilisé en moins de 3 mois via les économies de temps CI + productivité développeur. Le ROI d'une refonte est rarement aussi rapide à calculer.


#Les pièges à éviter

La liste des erreurs que nous avons faites — ou que nous avons vues sur des projets clients arrivés en consultation après une première tentative ratée.

Pièges courants :

  1. Versionner les packages internes — les packages internes d'un monorepo n'ont pas besoin de versioning sémantique. Utiliser workspace:* en pnpm, pas 1.0.0. Le versioning est pour les packages publiés sur npm.

  2. Oublier les variables d'environnement dans globalEnv — si une variable NEXT_PUBLIC_API_URL change entre staging et production mais n'est pas dans globalEnv, Turborepo peut servir un build caché avec la mauvaise URL.

  3. Créer trop de packages trop tôt — commencez par 3-4 packages évidents (ui, schemas, utils, config). N'extrayez pas chaque fonctionnalité en package dès le départ. Le coût d'abstraction prématurée dans un monorepo est le même que partout ailleurs.

  4. Ignorer les dépendances circulairesapps/portail-client ne doit jamais importer depuis apps/marketing. Si vous en trouvez, c'est que du code doit être extrait dans un libs/.

  5. Négliger le .gitignore des node_modules — dans un monorepo pnpm, les node_modules sont à la racine ET dans chaque package. Le .gitignore doit couvrir les deux.

La migration Next.js 16 vers un monorepo gagne à être préparée en amont — les App Router changes de Next.js 16 simplifient certaines configurations de cache qui compliquaient les anciens monorepos Pages Router.

Questions & Réponses

Questions fréquentes sur Turborepo monorepo Next.js

Oui, à partir de 2 applications Next.js qui partagent du code. La configuration initiale prend une demi-journée, et les gains (CI plus rapide, code partagé sans friction) sont visibles immédiatement. Pour une seule app Next.js sans perspective de créer d'autres apps, le monorepo n'apporte pas grand-chose. Mais dès qu'une deuxième app apparaît — portail client, back-office, site marketing séparé — Turborepo devient rentable rapidement. Le seuil minimal : 2 apps + au moins 1 package partagé (design system ou utils).
Turborepo fonctionne avec npm, yarn et pnpm. En pratique, pnpm est fortement recommandé pour les monorepos en 2026 pour trois raisons : la gestion des workspaces est plus robuste (résolution de dépendances entre packages plus fiable), l'installation est significativement plus rapide (architecture de stockage en liens symboliques vs copies), et le `workspace:*` de pnpm permet de référencer les packages locaux sans versionning. Si vous partez de zéro, commencez avec pnpm. Si vous avez déjà un projet en yarn, la migration pnpm prend généralement une demi-journée et vaut l'investissement.
Chaque app conserve son propre fichier `.env.local` — le monorepo ne change pas la gestion des secrets. Ce qui change : les variables qui influencent le build (surtout les `NEXT_PUBLIC_*`) doivent être déclarées dans `globalEnv` de `turbo.json` pour être incluses dans le hash de cache. Si elles ne le sont pas, Turborepo peut restaurer un build caché produit avec une autre valeur de variable — ce qui peut provoquer des bugs silencieux en production. En CI, chaque app a ses propres secrets GitHub Actions. La règle : les secrets de production restent isolés par app, mais les variables qui affectent le build sont rendues explicites dans `turbo.json`.
Oui. Le remote caching Turborepo est agnostique de la plateforme CI — il communique via une API REST standard. Sur GitLab CI, la configuration est identique à GitHub Actions : injecter `TURBO_TOKEN` et `TURBO_TEAM` comme variables CI/CD. Jenkins nécessite la même chose dans les variables de credential. Si vous ne pouvez pas utiliser Vercel comme fournisseur de cache (contraintes réseau, souveraineté), le serveur de cache self-hosted `turborepo-remote-cache` peut être déployé sur votre infrastructure interne et configuré via `TURBO_API` pointant vers votre endpoint.
Absolument — c'est même un des cas d'usage les plus convaincants. Les schémas Zod de validation, les types TypeScript des entités métier, les constantes d'erreur, les DTOs — tous peuvent vivre dans des packages `libs/` consommés à la fois par les Server Actions Next.js et les controllers NestJS. La clé : ces packages partagés doivent être du TypeScript pur sans dépendances sur des framework-spécifiques. Les schémas Zod sont particulièrement précieux car ils valident les données côté front (formulaires) et côté back (entrée API) avec exactement la même logique — une seule source de vérité.
`--filter` est explicite : vous spécifiez quels packages exécuter. `turbo build --filter=marketing` builde uniquement l'app marketing et ses dépendances. `--affected` (ou `--filter='...[HEAD^1]'`) est dynamique : Turborepo calcule les packages affectés depuis le dernier commit ou depuis une branche de référence. En pratique : utilisez `--filter` quand vous savez exactement ce que vous voulez cibler (ex. déployer une seule app), et `--filter='...[origin/main]'` en CI pour ne builder que ce qui a changé depuis main. La combinaison remote caching + `--filter` affected est ce qui produit les réductions de 80% de temps CI.
Non — si votre équipe est productive avec Nx et que le projet tourne bien, la migration vers Turborepo n'apporte pas de bénéfice justifiant le coût. Nx et Turborepo ont des philosophies différentes mais des capacités similaires pour la majorité des cas d'usage. La migration inverse (Turborepo → Nx) peut se justifier si vous atteignez les limites de Turborepo sur les projets très larges (50+ packages, multi-frameworks, besoins de generators). Le conseil pragmatique : choisissez l'outil adapté à votre contexte au démarrage, ne migrez pas d'un outil fonctionnel vers un autre sans bénéfice concret mesuré.
Réserver un audit