Quando si lavora su progetti software di una certa complessità, la scelta tra monorepo e polyrepo può avere un impatto significativo sulla produttività del team e sulla scalabilità del codice. In questo articolo analizziamo le differenze, i pro e i contro di ciascun approccio, e ti aiutiamo a capire quale fa al caso tuo.
Cosa sono Monorepo e Polyrepo?
Monorepo
Un monorepo (monolithic repository) è un singolo repository che contiene il codice sorgente di più progetti, servizi o pacchetti, spesso correlati tra loro.
my-monorepo/ packages/ frontend/ backend/ shared/ package.json turbo.json
Polyrepo
Un polyrepo (multiple repositories) prevede che ogni progetto, servizio o pacchetto abbia il proprio repository separato.
repos/ frontend/ package.json backend/ package.json shared/ package.json
Differenza visiva
Pro e Contro
Monorepo
Vantaggi:
- Facilita la condivisione di codice (es. librerie condivise).
- Refactoring atomico su più progetti.
- Gestione centralizzata delle dipendenze e delle configurazioni.
Svantaggi:
- Può diventare pesante con la crescita del codice.
- Richiede strumenti per gestire build/test parziali (es. Nx, Turborepo).
Polyrepo
Vantaggi:
- Ogni team/progetto è indipendente.
- Più semplice da gestire per piccoli progetti.
- Permette policy di accesso granulari.
Svantaggi:
- Difficile condividere codice senza pubblicare pacchetti.
- Refactoring cross-repo più complesso.
- Possibile duplicazione di configurazioni.
Esempio pratico: Monorepo con Turborepo
Supponiamo di voler creare un monorepo con frontend e backend usando Turborepo.
1. Inizializza il monorepo
npx create-turbo@latest
2. Struttura tipica
my-monorepo/ apps/ web/ # frontend Next.js api/ # backend Node.js/Express packages/ ui/ # libreria di componenti condivisi utils/ # funzioni condivise turbo.json package.json
3. Esempio di workspace in package.json
{ "private": true, "workspaces": [ "apps/*", "packages/*" ] }
4. Esempio di importazione di una libreria condivisa
Supponiamo di avere una funzione in packages/utils/src/formatDate.ts
:
// packages/utils/src/formatDate.ts export function formatDate(date: Date): string { return date.toLocaleDateString('it-IT'); }
Nel frontend:
// apps/web/pages/index.tsx import { formatDate } from '@myorg/utils'; export default function Home() { return <div>Oggi è {formatDate(new Date())}</div>; }
Quando scegliere Monorepo?
- Team medio-grandi che lavorano su più progetti correlati.
- Necessità di condividere codice e fare refactoring su larga scala.
- Progetti che crescono velocemente e richiedono build/test ottimizzati.
Quando scegliere Polyrepo?
- Progetti piccoli o indipendenti.
- Team separati che lavorano su prodotti diversi.
- Policy di accesso molto restrittive.
Conclusione
Non esiste una soluzione perfetta per tutti. La scelta dipende dalla dimensione del team, dalla complessità dei progetti e dalle esigenze di collaborazione. L’importante è essere consapevoli dei trade-off e scegliere gli strumenti giusti per gestire la complessità.