Monorepo avec TypeScript : organisation du code en pratique
\n\nDans le développement web moderne, en particulier lorsqu'on travaille avec TypeScript, les développeurs sont souvent confrontés à un dilemme : stocker tout le code dans un seul dépôt (monorepo) ou le diviser en plusieurs petits dépôts (polyrepo). Pour les projets de taille moyenne et grande, où la réutilisabilité du code et une configuration unifiée sont importantes, le monorepo devient un standard de facto. Dans cet article, nous allons voir comment organiser correctement un monorepo en TypeScript, de la structure de base aux techniques avancées.
\n\nQu'est-ce qu'un monorepo et pourquoi en a-t-on besoin ?
\n\nUn monorepo est une approche où le code de plusieurs projets (packages, bibliothèques, applications) est stocké dans un seul dépôt. Dans le contexte de TypeScript, c'est particulièrement pratique car cela permet :
\n\n- \n
- Réutiliser les types et les interfaces entre différentes parties du système sans publication sur npm. \n
- Simplifier le refactoring : une modification dans un package est automatiquement validée dans tous les packages dépendants. \n
- Avoir une configuration unifiée pour le linter, le formateur et le builder. \n
- Simplifier le CI/CD : un dépôt, un pipeline. \n
Parmi les outils populaires pour travailler avec les monorepos en TypeScript, on distingue Nx, Turborepo et npm/yarn/pnpm workspaces. Nous allons aborder l'approche utilisant pnpm workspaces et TypeScript Project References, car c'est un ensemble minimal et flexible.
\n\nStructure du monorepo : configuration de base
\n\nCréons une structure typique de monorepo pour un projet TypeScript. Supposons que nous ayons trois packages : core (types et utilitaires communs), server (backend) et web (frontend).
1. Configuration racine
\n\nCommençons par la racine du projet. Créons un fichier package.json avec workspace :
{\n "name": "my-monorepo",\n "private": true,\n "workspaces": [\n "packages/*"\n ],\n "scripts": {\n "build": "tsc -b",\n "clean": "tsc -b --clean",\n "lint": "eslint packages/*/src"\n }\n}\n\n\nEnsuite, configurons le tsconfig.json racine. Utilisons Project References — c'est une fonctionnalité clé de TypeScript pour les monorepos :
{\n "compilerOptions": {\n "target": "ES2020",\n "module": "commonjs",\n "strict": true,\n "composite": true,\n "declaration": true,\n "declarationMap": true,\n "sourceMap": true,\n "outDir": "./dist",\n "rootDir": ".",\n "skipLibCheck": true\n },\n "references": [\n { "path": "./packages/core" },\n { "path": "./packages/server" },\n { "path": "./packages/web" }\n ]\n}\n\n\nImportant : l'option composite: true est obligatoire pour les packages référencés par d'autres packages. Elle active la compilation incrémentale et la génération de fichiers .d.ts.
2. Configuration du package core
\n\nAllons dans packages/core. Créons un package.json :
{\n "name": "@my/core",\n "version": "1.0.0",\n "main": "dist/index.js",\n "types": "dist/index.d.ts",\n "scripts": {\n "build": "tsc -b"\n }\n}\n\n\nEt le tsconfig.json pour ce package :
{\n "extends": "../../tsconfig.json",\n "compilerOptions": {\n "outDir": "./dist",\n "rootDir": "./src"\n },\n "include": ["src"]\n}\n\n\nCréons un module simple src/index.ts :
export interface User {\n id: string;\n name: string;\n email: string;\n}\n\nexport function greet(user: User): string {\n return `Hello, ${user.name}!`;\n}\n\n\nMaintenant, le package
Blogs
Book Recommendations
Lire aussi
Travailler avec les dates et l'heure en Go : des bases aux techniques avancées
Contribution open source en C# : par où commencer sans perdre la tête
Lire un fichier ligne par ligne en C++ : ifstream et 5 erreurs fatales
Comment obtenir l'aperçu d'une vidéo YouTube via l'API : 5 erreurs fatales en PHP
Comment vérifier la qualité d'un cours Python avant de l'acheter