# Architecture d’un monorepo Next.js et WordPress headless avec Turborepo

> Organiser un thème WordPress minimal, des types générés et un front Next.js dans un même monorepo, avec mise en cache intelligente des builds via Turborepo.

- Auteur : Clément Hadrot
- Publié le : 2022-05-24
- Mis à jour le : 2022-05-24
- Catégorie : Headless &amp; API
- URL : https://wpmoderne.dev.wordpress-developpement.fr/headless/monorepo-nextjs-wordpress-headless-turborepo/

## L’essentiel

- Un seul dépôt pour trois briques qui évoluent ensemble
- Turborepo évite de reconstruire ce qui n'a pas changé
- Les types partagés circulent sans publication npm

À mesure qu'un projet headless grandit, la question de l'organisation des dépôts finit toujours par se poser : faut-il un dépôt pour le thème WordPress minimal, un autre pour le front Next.js, un troisième pour les types partagés ? Sur un projet e-commerce récent, cette dispersion avait fini par ralentir l'équipe, chaque modification de type obligeant à publier un paquet npm intermédiaire avant de pouvoir l'utiliser côté front. Ce billet décrit l'architecture en monorepo Turborepo mise en place pour régler ce problème, sans revenir sur la génération de types elle-même, déjà détaillée dans un autre article de ce blog.

## La structure retenue

```
mon-projet/
├── apps/
│   ├── front/                 # Application Next.js
│   │   ├── app/
│   │   ├── package.json
│   │   └── next.config.js
│   └── wp-theme/              # Thème WordPress minimal (pas de rendu)
│       ├── functions.php
│       └── style.css
├── packages/
│   ├── types-wp/              # Types TypeScript générés depuis le schéma WPGraphQL
│   │   ├── src/index.ts
│   │   └── package.json
│   └── ui/                    # Composants React partagés (boutons, cartes produit)
│       ├── src/
│       └── package.json
├── turbo.json
└── package.json
```

Le thème WordPress, volontairement minimal, ne sert qu'à déclarer les types de contenu personnalisés et les réglages GraphQL, sans jamais générer de rendu HTML destiné à un visiteur. Il vit néanmoins dans le même dépôt, ce qui permet de versionner ensemble une modification de type de contenu PHP et le type TypeScript correspondant, dans un seul et même commit.

## Le fichier turbo.json, cœur de l'organisation des tâches

```
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**"]
    },
    "generate-types": {
      "cache": false
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "lint": {
      "outputs": []
    }
  }
}
```

La clé `dependsOn: ["^build"]` indique à Turborepo que la tâche `build` d'un paquet dépend d'abord du `build` de ses dépendances internes : avant de compiler `apps/front`, Turborepo s'assure que `packages/types-wp` et `packages/ui` sont déjà construits à jour. La tâche `generate-types`, elle, reste explicitement non mise en cache, car elle dépend de l'état courant du schéma WPGraphQL exposé par WordPress, une donnée externe que Turborepo ne peut pas suivre par empreinte de fichiers.

> L'essentiel à retenir : Un seul dépôt pour trois briques qui évoluent ensemble ; Turborepo évite de reconstruire ce qui n'a pas changé ; Les types partagés circulent sans publication npm

## La mise en cache des builds, le vrai gain au quotidien

Sur ce projet, une modification isolée dans `packages/ui` ne déclenche la reconstruction que de ce paquet et de tout ce qui en dépend, jamais du thème WordPress qui n'a pas changé. Turborepo calcule une empreinte à partir du contenu réel des fichiers concernés, et restaure le résultat depuis le cache local, ou depuis un cache distant partagé par l'équipe, si l'empreinte correspond à un build déjà réalisé ailleurs :

```
$ turbo run build

• Packages in scope: front, types-wp, ui, wp-theme
• Running build in 4 packages
types-wp:build: cache hit, replaying output
ui:build: cache miss, executing
front:build: cache miss, executing
wp-theme:build: cache hit, replaying output

Tasks:    4 successful, 4 total
Cached:   2 cached, 4 total
Time:     18.4s (saved 41.2s)
```

Sur un projet où seule une petite partie change à chaque commit, ce gain se traduit directement par des temps d'intégration continue plus courts, sans rien sacrifier sur la fiabilité des builds.

## Faire circuler les types sans publication npm

Le paquet `packages/types-wp` est référencé directement dans le `package.json` de `apps/front` via le protocole de dépendance locale des gestionnaires de paquets modernes :

```
{
  "dependencies": {
    "@mon-projet/types-wp": "workspace:*"
  }
}
```

Aucune publication sur un registre npm, même privé, n'est nécessaire : le gestionnaire de paquets crée un lien symbolique local vers le paquet du monorepo, ce qui permet de modifier un type et de voir immédiatement l'effet côté front, sans étape de publication intermédiaire à attendre.

## Les limites rencontrées

- Le thème WordPress lui-même reste déployé séparément sur l'hébergement WordPress, le monorepo n'unifie que le code source, pas le déploiement final.
- L'équipe a dû s'habituer à la discipline des espaces de travail (workspaces), en particulier pour éviter d'installer une dépendance au mauvais niveau du monorepo.
- Le cache distant de Turborepo demande une configuration d'accès à un compte Vercel ou un serveur de cache auto-hébergé, une étape supplémentaire à ne pas négliger dans la mise en place initiale.

> Un monorepo n'apporte de valeur que si les briques qu'il regroupe évoluent réellement ensemble : forcer un thème WordPress et un front dans le même dépôt sans lien de dépendance réel n'apporterait aucun bénéfice, seulement de la complexité.

## En résumé

Sur ce projet, Turborepo a permis de faire cohabiter le thème WordPress minimal, les types générés et le front Next.js dans une seule base de code cohérente, avec des builds nettement plus rapides grâce à la mise en cache par empreinte de fichiers. Ce n'est pas une architecture universelle : elle prend tout son sens à partir du moment où plusieurs paquets internes dépendent réellement les uns des autres, ce qui était précisément le cas sur ce projet e-commerce en pleine croissance.
