{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", "dist/**"]
},
"lint": {},
"dev": {
"cache": false,
"persistent": true
}
}
}Am avut recent de gestionat un proiect destul de măricel: un dashboard de admin, o aplicație pentru clienți și un site de prezentare. Toate scrise în Next.js. Partea interesantă? Împărțeau cam 80% din componentele de UI (butoane, formulare, tabele) și aproape toată logica de autentificare și apeluri API.
La început, am vrut să scăpăm ieftin și să le ținem în repo-uri separate. Am renunțat rapid după ce am realizat că un simplu update la un buton de login însemna trei Pull Request-uri diferite și mult copy-paste. Așa că am decis să trecem pe monorepo. Am testat trei variante: npm workspaces simple, Nx și Turborepo.
De ce am zis pas la simple workspaces
Am vrut să fiu minimalist. Am configurat rapid workspaces în npm, fără alte tool-uri. În primele două zile a fost idilic. Problema a apărut când am vrut să rulăm build-ul în CI/CD (folosim GitHub Actions).
Workspaces simple nu știu ce s-a modificat cu adevărat. Dacă modifici o virgulă în pachetul de utilitare, npm va rula build-ul pentru toate cele trei aplicații de la zero. La proiectul nostru, asta însemna un build time de vreo 8 minute. Total ineficient și costisitor.
Nx: Prea multă magie pentru o echipă mică
Am trecut apoi la Nx. Este un tool extrem de capabil, dar am simțit că aducem un tanc la o vânătoare de iepuri.
Are generatoare de cod, grafice vizuale de dependențe și o tonă de configurări în fișiere JSON gigantice. Pentru o echipă de 4 oameni, complexitatea aia ne-a blocat. Am pierdut o zi întreagă doar încercând să facem compiler-ul Next.js (SWC) să se înțeleagă cu configurările lor custom de TypeScript.
Trade-off-ul e simplu: Nx e genial dacă ai 20+ aplicații și o echipă dedicată de Platform Engineering. Dacă vrei doar să livrezi cod rapid, te va încurca.
Câștigătorul: Turborepo și structura pe care am rămas
Am ales Turborepo și a fost cea mai bună decizie. S-a configurat în mai puțin de jumătate de oră. Folosește pnpm sub capotă și adaugă un strat de caching extrem de rapid scris în Rust. Știe exact ce fișiere s-au schimbat și face build doar la ce este nevoie.
Am redus timpul de build în CI de la 8 minute la doar 3 minute, salvând cam 60% din resurse.
Structura finală a proiectului arată așa:
apps/admin(Next.js)apps/client(Next.js)apps/landing(Next.js)packages/ui(componentele shadcn/ui comune)packages/utils(clienții de API, helperi, tipuri de TypeScript)
Dezavantajul la Turborepo? Spre deosebire de Nx, nu are generatoare automate. Dacă vrei un pachet nou, trebuie să-i creezi manual folderul, să-i scrii package.json-ul și să-l legi în workspace. Mie personal mi se pare un preț mic de plătit pentru simplitate.
Voi cum vă gestionați monorepo-urile? Mergeți pe pnpm simplu sau ați trecut deja la tool-uri dedicate?