Le monorepo Nx

Naviguer dans le codebase BootcodeMonorepo

Bootcode IWA-S04 — Semaine 20, Jour 1

Objectifs de la leçon

1. Savoir naviguer dans le monorepo Bootcode

Comprendre l'organisation apps/, packages/, et leurs sous-dossiers

2. Comprendre le rĂ´le de project.json et tsconfig.base.json

Les deux fichiers de configuration qui pilotent tout le monorepo

3. Lister les bounded contexts et leurs contenus

Cartographier les domaines fonctionnels du codebase

4. Utiliser les commandes npx nx build/serve/test

Maîtriser le CLI Nx pour exécuter les cibles de chaque projet

Plan du cours

1

Qu'est-ce qu'un monorepo et pourquoi Bootcode en utilise un (Nx)

Motivations : partage de code, builds optimisés, dépendances unifiées

2

Naviguer dans la structure

apps/, packages/, tsconfig.base.json, project.json

3

Les path aliases

Comment 'iac-core' pointe vers packages/iac/core/

4

Les commandes Nx

npx nx serve, build, test, lint

5

Tour guidé dans VS Code

Ouvrir le monorepo et naviguer dans les dossiers

Monorepo vs multi-repos

Un seul dépôt Git pour tous les packages

📦

Multi-repos

Un repo par package. Synchronisation manuelle des versions.

🗂️

Monorepo

Un seul repo. Partage de code natif, builds unifiés.

Pourquoi Bootcode utilise un monorepo

Partage de code natif

Les packages iac-core, shared sont importés directement, sans publish npm.

Builds optimisés

Nx ne recompile que ce qui a changé (cache + graphe de dépendances).

Dépendances unifiées

Une seule version de TypeScript, Express, TypeORM pour tout le monde.

Refactoring cross-package

Renommer un symbole touche tous les packages dans un seul commit.

💡 Nx est l'outil qui gère ce monorepo : il connaît le graphe de dépendances entre projets et optimise les builds.

Monorepo ≠ monolithe

Un monorepo peut contenir des services indépendants.

❌ Monolithe

Une seule application. Tout le code dans une seule base. Pas de frontières entre domaines.

âś… Monorepo

Plusieurs projets (apps + packages) dans un dépôt. Chacun a son project.json, ses tests, son build.

⚠️ Piège classique : confondre les deux. Bootcode est un monorepo avec une architecture en bounded contexts, pas un gros monolithe.

La structure du monorepo

Trois niveaux : apps > packages > core/adapters/messages

# BootcodeMonorepo/

apps/

giraffe/ # l'application backend (Express)

web/ # le frontend React

packages/

iac/ # Infrastructure as Code

core/ # le domaine (agrégats, use cases, events)

adapters/ # les implémentations (TypeORM, Express...)

messages/ # les événements asynchrones et handlers

tsconfig.base.json # path aliases globaux

nx.json # configuration Nx

đź’ˇ Chaque dossier sous packages/ est un bounded context. Chaque sous-dossier (core/adapters/messages) est un projet Nx.

project.json — la carte d'identité d'un projet

Chaque projet Nx a son propre project.json qui déclare ses cibles (targets).

// packages/iac/core/project.json

{

"name": "iac-core",

"sourceRoot": "packages/iac/core/src",

"targets": {

"build": { "executor": "@nx/js:tsc" ... },

"test": { "executor": "@nx/jest:jest" ... },

"lint": { "executor": "@nx/eslint:lint" ... }

}

}

đź’ˇ Les targets (build, test, lint, serve) sont les actions qu'on lance via npx nx <target> <project>.

tsconfig.base.json — les path aliases

Le fichier qui mappe les noms d'imports vers les dossiers physiques.

// tsconfig.base.json (racine du monorepo)

{

"compilerOptions": {

"baseUrl": ".",

"paths": {

"@bootcode/iac-core": ["packages/iac/core/src/index.ts"],

"@bootcode/iac-adapters": ["packages/iac/adapters/src/index.ts"],

"@bootcode/shared": ["packages/shared/src/index.ts"]

}

}

}

💡 Grâce aux aliases, on importe @bootcode/iac-core au lieu de ../../../packages/iac/core/src.

Les path aliases en action

De l'alias TypeScript à l'import réel

« Quand tu écris import { User } from '@bootcode/iac-core', TypeScript sait exactement où chercher. »

Import propre vs import relatif

❌ Import relatif

import { User } from '../../../../packages/iac/core/src/domain/user';

Casse si on déplace le fichier. Illisible. Fragile.

âś… Import par alias

import { User } from '@bootcode/iac-core';

Stable. Lisible. Résolu par tsconfig.base.json.

đź’ˇ L'index.ts de chaque package exporte l'API publique. On n'importe jamais un fichier interne directement.

Les commandes Nx

Tout passe par npx nx <target> <project> — pas de scripts npm à la racine.

# Lancer le serveur de dev de l'app giraffe

npx nx serve giraffe

# Builder le package iac-core

npx nx build iac-core

# Lancer les tests d'un projet

npx nx test iac-core

# Linter un projet

npx nx lint iac-core

# Voir le graphe de dépendances

npx nx graph

⚠️ Toujours npx devant nx — sans npx, la commande n'est pas trouvée.

Nx optimise les builds

Nx connaît le graphe de dépendances entre projets et ne recompile que le nécessaire.

📊

Graphe de dépendances

Nx sait que giraffe dépend de iac-core

⚡

Cache

Si rien n'a changé, le build est instantané (cache hit)

🎯

Build affecté

npx nx affected build ne build que les projets touchés

💡 C'est ça la vraie puissance d'un monorepo outillé : on partage le code SANS payer le coût des builds complets à chaque fois.

Pièges courants

❌ Confondre monorepo et monolithe

Un monorepo peut contenir des services indépendants. Bootcode a des frontières claires entre bounded contexts.

⚠️ Se perdre dans la structure

Rester focalisé sur les 3 niveaux : apps > packages > core/adapters/messages. Ne pas explorer au hasard.

❌ Oublier npx devant nx

nx serve giraffe ne marche pas. Il faut npx nx serve giraffe.

Ă€ retenir !

✅ Un monorepo = un seul dépôt Git avec plusieurs packages — pas plusieurs repos séparés.

✅ Nx gère les dépendances entre packages et optimise les builds (cache + graphe).

âś… Les path aliases dans tsconfig.base.json permettent des imports propres entre packages.

✅ Tout passe par npx nx <target> <project> — pas de scripts npm à la racine.

Demain : on plonge dans le démarrage de l'app backend 🚀