Cuando se trabaja en proyectos de software complejos, la elección entre monorepo y polyrepo puede tener un impacto significativo en la productividad del equipo y la escalabilidad del código. En este artículo analizamos las diferencias, los pros y los contras de cada enfoque, y te ayudamos a entender cuál es el más adecuado para ti.
¿Qué son Monorepo y Polyrepo?
Monorepo
Un monorepo (monolithic repository) es un único repositorio que contiene el código fuente de varios proyectos, servicios o paquetes, a menudo relacionados entre sí.
my-monorepo/ packages/ frontend/ backend/ shared/ package.json turbo.json
Polyrepo
Un polyrepo (multiple repositories) implica que cada proyecto, servicio o paquete tiene su propio repositorio separado.
repos/ frontend/ package.json backend/ package.json shared/ package.json
Diferencia visual
Pros y contras
Monorepo
Ventajas:
- Facilita el intercambio de código (por ejemplo, bibliotecas compartidas).
- Refactorización atómica en varios proyectos.
- Gestión centralizada de dependencias y configuraciones.
Desventajas:
- Puede volverse pesado a medida que crece el código.
- Requiere herramientas para gestionar builds/tests parciales (por ejemplo, Nx, Turborepo).
Polyrepo
Ventajas:
- Cada equipo/proyecto es independiente.
- Más fácil de gestionar para proyectos pequeños.
- Permite políticas de acceso granulares.
Desventajas:
- Difícil compartir código sin publicar paquetes.
- Refactorización entre repositorios más compleja.
- Posible duplicación de configuraciones.
Ejemplo práctico: Monorepo con Turborepo
Supongamos que quieres crear un monorepo con frontend y backend usando Turborepo.
1. Inicializa el monorepo
npx create-turbo@latest
2. Estructura típica
my-monorepo/ apps/ web/ # frontend Next.js api/ # backend Node.js/Express packages/ ui/ # biblioteca de componentes compartidos utils/ # funciones compartidas turbo.json package.json
3. Ejemplo de workspace en package.json
{ "private": true, "workspaces": [ "apps/*", "packages/*" ] }
4. Ejemplo de importación de una biblioteca compartida
Supongamos que tienes una función en packages/utils/src/formatDate.ts
:
// packages/utils/src/formatDate.ts export function formatDate(date: Date): string { return date.toLocaleDateString('es-ES'); }
En el frontend:
// apps/web/pages/index.tsx import { formatDate } from '@myorg/utils'; export default function Home() { return <div>Hoy es {formatDate(new Date())}</div>; }
¿Cuándo elegir Monorepo?
- Equipos medianos o grandes que trabajan en varios proyectos relacionados.
- Necesidad de compartir código y realizar refactorizaciones a gran escala.
- Proyectos que crecen rápidamente y requieren builds/tests optimizados.
¿Cuándo elegir Polyrepo?
- Proyectos pequeños o independientes.
- Equipos separados que trabajan en productos diferentes.
- Políticas de acceso muy restrictivas.
Conclusión
No existe una solución perfecta para todos. La elección depende del tamaño del equipo, la complejidad de los proyectos y las necesidades de colaboración. Lo importante es ser consciente de los trade-offs y elegir las herramientas adecuadas para gestionar la complejidad.