{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", "dist/**"]
},
"lint": {
"dependsOn": ["^lint"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}Salutare tuturor. Am pe cap o refactorizare la un proiect cu 3 aplicații Next.js (admin dash, un portal B2B și o platformă publică B2C) care împart aproape 80% din UI și logica de validare. Am adunat mai jos experiența mea cu cele trei opțiuni mari de pe piață și dilemele legate de arhitectură.
De la repo-uri separate la iadul de sync manual
Inițial am plecat cu repo-uri separate. Copiam componentele Button, Modal și Form dintr-un loc în altul ca barbarii. Când schimbi o culoare în design system și trebuie să faci 3 commit-uri în 3 locuri diferite, îți dai seama repede că pierzi vremea degeaba.
Am decis să trecem la monorepo. Întrebarea firească a fost: ce tooling folosim ca să nu ne complicăm viața inutil, dar să avem totuși un build rapid în CI?
pnpm Workspaces simple: Rapid la setup, dureros la CI
Prima tentativă a fost cu pnpm workspaces curat, fără niciun alt orchestrator. Împachetezi totul în apps/ și packages/, faci link-uri simbolice interne și gata.
Bubele apar repede. Workspaces-urile simple nu știu să facă caching inteligent la task-uri. Când dai build pe serverul de CI, recompilează absolut tot, chiar dacă ai schimbat doar un text în aplicația de admin. La noi, un pipeline simplu de GitHub Actions ajunsese la 11 minute pe fiecare Pull Request. Merge bine pentru pachete mici, dar e nasol rău când crește numărul de pachete interdependente.
Nx: Genial, dar o idee prea complex pentru cazul nostru
Am testat apoi Nx. Generatoarele lor sunt fantastice, iar graph-ul vizual de dependențe e super util când vrei să vezi ce e legat de ce.
Marea mea problemă cu Nx pe un stack pur Next.js a fost configurația stufoasă. Fișiere peste fișiere specifice, un abstraction layer peste configurația nativă de Next.js și un learning curve destul de abrupt pentru colegii mai juniori. Dintr-o dată, schimbarea unei opțiuni de TypeScript necesita să înțelegi exact cum pasează Nx contextul. Dacă ai o echipă de 20+ devi și repo-uri gigant, se justifică. Pentru 3 aplicații, simțeam că tragem cu tunul după vrăbii.
Turborepo: Punctul dulce pentru Next.js
Până la urmă am mers pe Turborepo. L-am configurat în vreo 30 de minute direct peste pnpm workspaces.
Ce îmi place la el e că nu încearcă să-ți controleze tot proiectul. E doar un orchestrator de task-uri paralel care știe caching local și remote. Dacă nu s-a schimbat nimic în packages/ui, când dai turbo build își ia artefactele direct din cache în câteva milisecunde. Am scăzut build time-ul în CI de la 11 minute la sub 3 minute, salvând cam 65% din timpul de pipeline.
Structura pe care am mers și mici capcane
Structura finală arată cam așa:
├── apps/
│ ├── admin/
│ ├── portal-b2b/
│ └── web-b2c/
└── packages/
├── ui/ (Tailwind CSS + Radix)
├── config-typescript/
└── utils/
Marea bătaie de cap la componente partajate de Next.js (App Router) este configurarea de Tailwind CSS și importul de componente din packages/ui. Trebuie neapărat să folosești opțiunea transpilePackages: ["@acme/ui"] în next.config.js pentru fiecare app, altfel te lovești de erori de bundling pe server side.
Voi ce soluție folosiți când aveți 2-3 proiecte legate strâns între ele? Ați rămas pe Turborepo sau ați simțit nevoia de funcționalitățile avansate din Nx?