La conversation monorepo commence souvent au mauvais endroit. Quelqu'un demande s'il est préférable d'avoir un ou plusieurs référentiels, comme s'il s'agissait d'une décision concernant l'organisation des dossiers. Ce n'est pas. Il s'agit d'une décision sur la façon dont les équipes coordonnent le travail, et le référentiel n'en est que la partie visible.
Avec TypeScript, cette décision acquiert une saveur spécifique et puissante : la possibilité de partager des types entre frontend, backend et bibliothèques internes au sein du même espace. C’est l’argument qui pousse les équipes sérieuses à se tourner vers le monorepo, et aussi l’argument qui cache les coûts que l’on ne découvre que plus tard.
Ce texte s'adresse à ceux qui décident de l'architecture et de l'organisation des équipes et qui doivent peser les deux côtés avant de s'inscrire.
Le vrai tirage au sort : le type de contrat live
Le gain le plus concret d'un monorepo avec TypeScript est le type partagé entre les extrémités du système. Le backend définit le format d'une réponse, le frontend consomme ce même format et ils pointent tous deux vers la même définition.
Lorsque le backend modifie le format des données, le frontend arrête immédiatement la compilation. Il n’y a pas de réunion d’alignement, il n’y a pas de document contractuel obsolète, il n’y a pas de bug classique où l’API a changé et personne n’a prévenu l’interface. Le compilateur devient le mécanisme de coordination entre les équipes.
Cela résout l’une des plus grandes sources de friction dans les systèmes distribués : la déconnexion entre ceux qui produisent les données et ceux qui les consomment. Dans des référentiels séparés, le contrat vit dans la confiance et la documentation. Dans le monorepo typé, le contrat réside dans le code et est vérifié à chaque commit. Quiconque souhaite aller encore plus loin dans cette garantie, de la banque à l'interface, mérite de s'intéresser à la sécurité de type de bout en bout avec tRPC, Drizzle et Prisma](/post/type-safety-ponta-a-ponta-trpc-drizzle-prisma).
Qu'apporte d'autre le monorepo
Outre les types, il existe des gains de coordination qui méritent d’être mentionnés. Un changement qui traverse le frontend et le backend s'inscrit dans un seul commit et une seule révision, au lieu de devenir une danse de pull request synchronisées entre les référentiels.
La normalisation est également plus facile. Une configuration lint, une version de TypeScript, un ensemble de règles de formatage qui s'appliquent à tout. Au lieu que chaque référentiel adopte son propre dialecte, l'équipe maintient une culture technique unique, ce qui réduit le coût de déplacement entre les projets.
Et il y a la réutilisation du code interne. Une bibliothèque de composants, un ensemble de fonctions utilitaires, des règles de domaine qui servent plusieurs applications. En monorepo, il s'agit d'un package interne que tout le monde consomme dans la version actuelle, sans le rituel de publication et de mise à jour des dépendances à chaque modification.
Les compromis que personne ne montre au début
Maintenant, l'autre moitié de l'histoire, pourquoi le monorepo bien fait est puissant et le monorepo mal fait est un point d'ancrage.
Le premier coût est la construction. Lorsque tout cohabite, vous avez besoin d'outils qui comprennent ce qui a changé et ne reconstruisent que ce qui est nécessaire, sinon chaque petit changement déclenche un processus lent qui grandit avec le référentiel. Sans mise en cache intelligente et sans construction incrémentielle, le temps de pipeline devient un problème quotidien pour l'équipe.
Le deuxième coût est la gouvernance. Un référentiel dans lequel n’importe qui peut importer n’importe quoi de n’importe où dégénère rapidement en un enchevêtrement de dépendances croisées. Le frontend finit par importer quelque chose qui n’avait de sens que dans le backend, et la séparation qui existait sur le papier disparaît dans la pratique. Monorepo nécessite des limites explicites et la discipline pour les maintenir.
Le troisième coût est moins technique et plus humain. Un référentiel unique signifie un point de coordination unique. Autorisations, propriétaires de code, révision, flux de publication. Tout cela commence à vivre dans le même espace, et les grandes équipes ont besoin de règles de propriété claires pour éviter de se marcher dessus à tout moment.
Quand ça vaut vraiment le coup
La décision devient plus simple lorsque l’on examine le profil du problème au lieu de suivre les tendances. Monorepo avec TypeScript brille lorsque le frontend et le backend appartiennent à la même équipe ou à des équipes très proches, et changent fréquemment ensemble.
Cela brille lorsqu’il existe un code de domaine véritablement partagé entre les applications, et le coût de sa synchronisation dans des référentiels distincts est déjà préjudiciable. Cela brille lorsque le contrat entre les couches change suffisamment pour que la vérification automatique du type paie l'investissement nécessaire à la mise en place du cadre.
En revanche, si les systèmes sont véritablement indépendants, évoluent à des rythmes différents et appartiennent à des équipes qui se parlent à peine, forcer un monorepo crée un couplage là où il n'y en avait pas. Vous payez pour la complexité sans récolter la coordination, car il n’y avait pas de coordination à collecter. Dans ce cas, des référentiels distincts avec des types publiés sous forme de package versionné sont souvent plus efficaces.
Ce qu'il faut considérer avant d'adopter
Avant de déplacer quoi que ce soit, il vaut la peine de répondre honnêtement à quelques questions, car les réponses déterminent si le monorepo vous aidera ou vous gênera.
Le premier concerne la maturité des outils. Disposez-vous, ou êtes-vous prêt à maintenir, l'infrastructure de construction et de mise en cache incrémentielle dont a besoin un monorepo sain ? Sans cela, le temps de pipeline érodera le gain de coordination. Il s’agit d’une décision d’investissement continue et non d’une configuration ponctuelle.
La seconde concerne la discipline aux frontières. L'équipe est-elle disposée à définir et à faire respecter des limites entre les colis, même si le passage de la frontière semble plus rapide à ce moment-là ? Le monorepo sans gouvernance devient du code spaghetti à plus grande échelle.
Le troisième concerne le problème que vous résolvez. Adoptez-vous le monorepo parce que le manque de types partagés provoque de réels bugs et frictions, ou parce qu'il est devenu standard et semble organisé ? La première raison justifie le coût. La seconde presque jamais.
La décision est une question d'organisation, pas de dossier
En fin de compte, le monorepo avec TypeScript est un choix visant à aligner la façon dont les équipes travaillent, le type partagé servant de ciment technique entre elles. Lorsque les équipes ont vraiment besoin de travailler ensemble, c'est l'une des structures les plus efficaces qui soient. Lorsqu’ils n’en ont pas besoin, c’est une complexité déguisée en bonne pratique.
Le leadership technique qui décide bien est celui qui sépare le gain réel, qui est la coordination vérifiable par le compilateur, de l'esthétique d'avoir tout au même endroit. Le premier justifie l’investissement. Le second est un piège coûteux.
Si vous réfléchissez à cette décision, commencez par déterminer comment vos équipes modifient le code ensemble aujourd'hui et où se situent les frictions. La structure du dépôt doit suivre la réalité du travail, et jamais l'inverse. Pour avoir une idée complète de la façon dont les types sous-tendent un système entier, cela vaut la peine de commencer par pourquoi TypeScript est devenu la norme.
A lire aussi
-Advanced TypeScript en pratique : ce qui sépare une utilisation superficielle d'une utilisation mature -Pourquoi TypeScript est devenu la norme sur le Web moderne
- Validation des données avec Zod : pourquoi les types TypeScript ne suffisent pas
- Serveur d'abord : la décision architecturale visant à alléger le poids du navigateur -Sécurité de type de bout en bout : du banc au frontend sans rompre aux frontières
- Micro-frontends : quand et pourquoi adopter dans des projets évolutifs
