{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"lint": {
"dependsOn": ["^lint"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}Am început refactoring-ul pentru trei aplicații Next.js 15: un portal pentru clienți, un panou de admin și un app B2B dedicat partenerilor. Toate folosesc același design system, aceleași tabele complexe, aceleași componente de forms și cam 80% din hook-urile de autentificare și fetching. Înainte aveam cod copiat cu copy-paste între repo-uri diferite, iar sincronizarea unui simplu fix de UI dura o veșnicie.
Am adus totul într-un singur repo, dar acum sunt la răscrucea clasică de tooling: pnpm workspaces simplu, Turborepo sau Nx.
Varianta 1: Doar pnpm workspaces
Am pornit inițial cu pnpm-workspace.yaml curat, fără niciun alt orchestrator. Structura e simplă: un folder apps/ pentru cele trei instanțe de Next și un folder packages/ unde am pus packages/ui, packages/hooks și packages/tailwind-config.
Avantajul e zero overhead mental. Nu ai unelte noi de configurat, nu înveți CLI-uri separate. Dar problema apare rapid în CI/CD: când deschizi un PR care modifică o virgulă într-un utilitar, GitHub Actions îți rulează next build și lint pe toate cele 3 aplicații de la zero. La proiectul nostru, asta înseamnă 6 minute pierdute la fiecare push, deși doar un app ar fi fost afectat.
Varianta 2: Turborepo
Am adăugat Turborepo peste workspace-ul de pnpm și diferența la build time s-a văzut instant. Cu local caching și Remote Caching pe Vercel, pipeline-ul de CI a scăzut de la 6 minute la 1 minut și 15 secunde pentru PR-urile care ating doar UI-ul comun.
Secretul ca să nu-ți prinzi urechile este să nu faci build separat pe pachetul de UI. Exporți componentele direct ca sursă TypeScript/TSX și lași fiecare aplicație Next.js să le compileze direct, folosind opțiunea transpilePackages: ['@repo/ui'] în next.config.js. Scapi de fișiere dist/ intermediare, iar Hot Module Reloading funcționează instant când editezi un buton.
Trade-off sincer: dacă ai configurări de Tailwind diferite între aplicații, scanarea claselor din packages/ui prin directiva content din Tailwind v3 e o mică bătaie de cap până nimeriți glob-urile exacte.
De ce am exclus Nx (momentan)
Am lucrat cu Nx pe un proiect bancar cu vreo 14 echipe și 40 de pachete. Dacă ai dependințe enterprise, generatoare automate de cod și backend-uri NestJS legate strâns de frontend, Nx e imbatabil.
Dar pentru trei aplicații Next.js și câteva pachete interne de UI, mi se pare complet overkill. E mult prea mult boilerplate, configurările de project.json devin stufoase, iar viteza de iterație a echipei scade până învață toată lumea cum funcționează dependency graph-ul lor.
Întrebare pentru voi
Cum ați rezolvat tema de CSS tokens și Tailwind când împărțiți componente între mai multe Next apps? Ați mers pe export de preset sau ați migrat deja la noile convenții din Tailwind v4 în monorepo?