Le curseur blanc dans VS Code a clignoté silencieusement, mais aucune indication de type n'est apparue. Le soupir frustré de mon collègue a résonné dans notre appel Slack – son ancienne machine avait finalement complètement abandonné les suggestions TypeScript. Après un an de création de notre application Next.js, nous nous sommes heurtés à un mur que je redoutais : notre base de code monolithique était devenue trop volumineuse pour être confortable.
Quand j'ai démarré ce projet, Next.js semblait être le choix parfait. Venant d'une expérience dans les React SPA simples avec React Router et Express – et d'expériences même antérieures avec PHP – l'idée de colocaliser le code serveur et client semblait intuitive. Conformément aux idées reçues, nous avons organisé notre code par fonctionnalité plutôt que par problèmes techniques. Authentification, prospects, comptes, fonctionnalités d'équipe – chacun vivait dans son propre module, avec ses propres types, utilitaires, constantes et code côté serveur.
"C'était beau au début", je me souviens avoir pensé pendant ces premiers mois. Travailler sur le module de comptes signifiait que tout ce dont vous aviez besoin était là – composants, hooks, fonctions tRPC et même fichiers Prisma – le tout dans un seul dossier. C'était l'expérience de développeur que j'avais toujours voulue.
Sept mois plus tard, les premiers signes avant-coureurs sont apparus. Le serveur de langage de TypeScript a commencé à avoir des difficultés, les suggestions sont apparues de plus en plus lentement et les temps de construction ont augmenté. Même si ma puissante machine de développement pouvait encore le gérer, l'ancien matériel de mon collègue s'est complètement rendu à la complexité.
Nous avons été confrontés à un carrefour d'ingénierie classique : investir de l'argent sur le problème ou investir des heures d'ingénierie pour le résoudre correctement. Bien sûr, nous pourrions mettre à niveau notre matériel – les performances de TypeScript n’ont d’impact que sur le développement, pas sur la production. Mais quelque chose dans cette solution ressemblait à un pansement. Nous avons choisi la voie la plus difficile : refactoriser notre monolithe en monorepo à l'aide de Turborepo.
La première étape a été étonnamment simple : migrer la structure sans diviser le code. J'ai créé un dossier d'applications contenant notre application Web et ajouté deux packages Turborepo standard pour la configuration ESLint et TypeScript. Mais le véritable test consisterait à déplacer nos fonctionnalités principales tout en préservant l'inférence de type.
J'ai commencé avec notre couche de base de données, en déplaçant tout le code lié à Prisma dans son propre package. Après quelques ajustements d'exportation package.json, j'ai retenu mon souffle et vérifié les types dans notre application principale. Ils ont parfaitement fonctionné. Mieux encore, lorsque mon collègue a apporté les modifications, il a reçu des suggestions IntelliSense pour la première fois depuis des semaines. Nous étions sur quelque chose.
Vient ensuite le tRPC, ce qui semblait logique : un autre élément autonome de fonctionnalité côté serveur. Mais c'est ici que les choses sont devenues intéressantes. Ce qui a commencé comme "juste déplacer tRPC" s'est transformé en une série de dépendances inattendues :
Cette migration m'a appris plusieurs leçons cruciales sur l'architecture et les pratiques de développement :
La séparation serveur-client est importante : bien que Next.js facilite le mélange du code serveur et client, cette commodité peut conduire à des architectures désordonnées. Je me suis retrouvé à importer des types et des constantes au-delà des frontières sans penser aux implications.
Commencez avec Monorepo : Si je recommençais aujourd'hui, je commencerais par Turborepo dès le premier jour. Cela ajoute une complexité minimale tout en vous obligeant à réfléchir aux dépendances et à l'architecture de manière saine.
Les dépendances explicites sont meilleures : Briser le monolithe nous a obligé à visualiser et à remettre en question nos relations de dépendance. Ces connexions sont-elles nécessaires ? Avons-nous créé des dépendances circulaires ? Ces contraintes nous ont poussés vers de meilleures décisions architecturales.
La migration n'est pas encore terminée. Notre code serveur et nos utilitaires partagés ont encore besoin d'une organisation appropriée, et nous repensons la structure de nos modules maintenant que les couches tRPC et base de données vivent séparément. Mais déjà, notre expérience de développement s'est considérablement améliorée.
Pour toute personne créant une application Next.js susceptible d'évoluer, envisagez de commencer avec une structure monorepo. L’investissement initial est minime, mais les garde-corps architecturaux qu’il offre sont inestimables. Votre futur moi – et les anciens ordinateurs portables de votre équipe – vous remercieront.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!