Ne-am trezit pe cap cu 3 aplicații Next.js (un portal pentru clienți, un dashboard intern de backoffice și un landing page public) care împart lejer 80% din design system și logica de autentificare. Încerc să decid structura monorepo-ului înainte să ne blocăm în producție, și aș vrea niște păreri de la oameni care s-au lovit deja de asta.
La jobul anterior am ținut două proiecte separate cu submodule Git și a fost un calvar curat: merge conflicts zilnice și cel puțin 40 de minute pierdute la fiecare release doar pe sincronizat versiuni de librării. De data asta vreau o structură curată. Avem în jur de 45 de componente de UI în Tailwind, plus câteva hook-uri custom de fetch și auth cu TanStack Query. Cerința mea de bază e simplă: devii să ruleze comanda de start și să aibă HMR instant dacă schimbă un buton în pachetul comun, fără să aștepte 15 secunde după rebuild-uri interne.
1. Turborepo cu pnpm workspaces
Prima variantă pe care am testat-o două zile a fost Turborepo. Mi-a plăcut că e minimalist: trântești un turbo.json, declari task-urile de build, lint, dev, iar caching-ul local chiar funcționează impecabil. La un build curat pe CI am coborât timpul de la 3 minute și 40 de secunde la doar 18 secunde când pachetele partajate nu aveau modificări.
Problema apare la cum gestionezi componentele în Next.js prin transpilePackages. Dacă expun direct TypeScript raw din pachetul @repo/ui, HMR-ul zboară în dev. În schimb, când vrei să adaugi teste izolate de Vitest sau un Storybook în pachetul de UI, încep durerile de cap cu path aliases și Tailwind-ul care trebuie recompilat din contextul fiecărei aplicații părinte. Dacă aleg să compilez pachetul separat cu tsup la fiecare salvare, dev experience-ul devine lent și enervant.
2. Nx: rachetă sau complexitate inutilă?
Am tras un ochi serios și peste Nx. Știu că e privit ca standardul matur când ai monorepo-uri enterprise, dar ultima oară când l-am configurat (acum vreo doi ani) m-am simțit ca și cum aș fi învățat un framework complet nou, nu un tool de build. Generatorii lor de cod sunt mișto, însă volumul de configurații generate mă sperie puțin.
Pe de altă parte, am prieteni care jură că graful de dependențe din Nx și caching-ul distribuit sunt singurele care nu crapă când echipa trece de 5-6 oameni activi pe repo. Trade-off-ul e evident: pierzi simplitatea. Dacă ceva se strică la un pas de bundle, ajungi să depanezi plugin-urile interne Nx în loc să inspectezi un simplu fișier de config de Node sau Next.
3. Doar pnpm workspaces, fără orchestrator
A treia variantă la care mă gândesc e cea minimalistă: doar pnpm-workspace.yaml și scripturi rulate clasic cu --filter. Fără magii, fără json-uri dedicate de pipeline.
Merge brici cât timp echipa e mică și numărul de pachete e redus. Zero dependențe externe de configurare, totul e transparent. Nasolul absolut e lipsa de computation caching: dacă schimbi un fișier într-un singur app, pe CI se reface totul de la capăt pe toate cele 3 aplicații. La 10-15 deploy-uri pe zi, mâncăm minutele de GitHub Actions într-o săptămână.
Cum ați rezolvat problema pachetelor de UI partajate între app-uri Next.js fără să vă prindeți urechile în transpilare? Merită complexitatea din Nx pentru doar 3 proiecte, sau Turborepo e suficient de stabil pe termen lung?