Cómo estructurar un monorepo sin que sea un infierno
- monorepo
- software
- arquitectura
- desarrollo
- productividad
Un monorepo es un único repositorio de Git que contiene múltiples proyectos de software, a menudo no relacionados entre sí. La idea no es nueva, pero ha ganado popularidad gracias a herramientas que resuelven los problemas de escala y rendimiento que antes hacían inviable este enfoque para la mayoría.
Si has considerado adoptar este enfoque, sabes que la promesa es tentadora: código compartido, dependencias simplificadas y builds más rápidos. Sin embargo, la realidad sin una buena estructura y las herramientas adecuadas puede ser un auténtico infierno.
Qué es un monorepo y por qué se confunde con un monolito
La diferencia entre un monorepo y un monolito no es el tamaño, sino la arquitectura interna de las aplicaciones. Un monolito es una única aplicación grande donde todos los componentes están fuertemente acoplados. Un monorepo es un contenedor de múltiples proyectos independientes, cada uno con su propia lógica y despliegue, pero compartiendo el mismo control de versiones.
Es como tener varios libros en una misma estantería —cada libro es independiente, pero se gestionan juntos en un único espacio. Esto facilita la consistencia en herramientas y la reutilización de código.
Por qué un monorepo puede acabar siendo un problema
El miedo a este tipo de repositorio no es infundado. Sin una estrategia clara, puede llevar a builds lentos, conflictos de dependencias y una dificultad extrema para entender dónde está cada cosa. La gente lo asocia con la complejidad precisamente por eso.
Mi regla es simple: si no vas a usar una herramienta de orquestación de tareas y un sistema de cache, no uses esta arquitectura. La gestión manual de dependencias y los builds completos de todos los proyectos cada vez que tocas algo es un camino directo al desastre.
Funciona bien si:
- Tienes múltiples aplicaciones o librerías que comparten código.
- Quieres mantener la consistencia en el tooling (linters, formatters, etc.).
- Necesitas una vista unificada del estado de todos tus proyectos.
Deja de funcionar cuando:
- Cada proyecto es totalmente independiente y no comparte nada.
- No hay inversión en herramientas que gestionen la complejidad.
- Los equipos son muy grandes y necesitan autonomía extrema en repositorios.
Herramientas de orquestación para monorepos
Un monorepo funcional requiere herramientas de orquestación de tareas como Turborepo o Nx. Estas herramientas no solo te permiten definir scripts para cada proyecto, sino que los ejecutan de forma eficiente. Utilizan la cache para no volver a ejecutar tareas que ya se hicieron y entienden las dependencias entre proyectos para construir solo lo necesario.
Por ejemplo, con Turborepo, un package.json puede definir tareas que el monorepo orquesta:
// packages/ui/package.json
{
"name": "@my-monorepo/ui",
"version": "1.0.0",
"scripts": {
"build": "tsc",
"test": "jest"
}
}
En el package.json raíz, Turborepo sabe cómo orquestar estas tareas, ejecutando build y test solo en los paquetes afectados o que necesitan ser actualizados. Esto es especialmente útil para evitar duplicar configuraciones de entorno. Aquí puedes ver cómo la configuración de entorno sin duplicar es vital.
Estructura de directorios: la clave del monorepo
Una estructura clara es necesaria para un monorepo manejable. La convención más extendida es separar las aplicaciones de las librerías compartidas:
mi-monorepo/
├── apps/
│ ├── web/ # Aplicación frontend
│ ├── api/ # API backend
│ └── admin/ # Panel de administración
├── packages/
│ ├── ui/ # Componentes UI compartidos
│ ├── utils/ # Funciones de utilidad comunes
│ ├── types/ # Definiciones de tipos TypeScript
│ └── auth/ # Lógica de autenticación compartida
├── .gitignore
├── package.json # Paquete raíz del monorepo
└── turbo.json # Configuración de Turborepo o nx.json
Esta estructura mantiene las responsabilidades claras. Las apps son los productos finales que se despliegan, mientras que los packages son módulos internos reutilizables.
Gestión de dependencias y CI/CD en un monorepo
La gestión de dependencias en un monorepo se simplifica porque todas las librerías internas se referencian por su nombre de paquete, no por rutas relativas. Esto significa que si web usa @my-monorepo/ui, la herramienta de paquetes (npm, yarn, pnpm) lo resolverá internamente.
En cuanto a la integración continua y el despliegue (CI/CD), herramientas como Turborepo o Nx mejoran significativamente el proceso. Permiten configurar workflows que solo ejecutan tests o builds para los proyectos que han cambiado, no para todo el monorepo. Esto acelera drásticamente los pipelines. Tengo un artículo sobre cómo automatizar tareas con GitHub Actions que se aplica perfectamente a este contexto.
Ventajas y desventajas de un monorepo
Adoptar esta arquitectura es una decisión con ventajas y desventajas claras.
Lo que ganas:
- Consistencia de código y herramientas: Todos los proyectos usan las mismas versiones de linters, formatters y compiladores.
- Reutilización de código: Es trivial compartir lógica, componentes UI o tipos entre proyectos.
- Gestión de dependencias simplificada: Una única
node_modules(con pnpm o yarn workspaces) y un solopackage.jsonraíz para dependencias globales. - Builds optimizados: Herramientas como Turborepo o Nx cachean resultados y solo procesan lo que ha cambiado.
Lo que complicas:
- Curva de aprendizaje: La configuración inicial de la herramienta de monorepo y la adaptación del equipo pueden llevar tiempo.
- Configuración de CI/CD: Aunque más eficiente a la larga, la configuración inicial puede ser más compleja para aprovechar sus capacidades.
- Tamaño del repositorio: El historial de Git puede crecer mucho, aunque esto es menos problemático hoy en día.
Lo que no negocias:
- Una herramienta de monorepo: Intentar este tipo de gestión sin Turborepo, Nx o similar es condenarse al fracaso.
- Disciplina en la estructura: Mantener la separación clara entre apps y packages.
- Un sistema de CI/CD robusto: Necesitas pipelines que aprovechen la inteligencia de esta configuración.
Si estás pensando en el rendimiento y la fiabilidad de tus proyectos, recuerda que el testing automatizado ahorra dinero a largo plazo, especialmente en entornos de monorepo. Y si tu monorepo incluye múltiples servicios, te interesará evaluar cuándo dividir en microservicios para mantener la coherencia.
Técnico freelance especializado en desarrollo a medida, automatizaciones con IA y gestión técnica para negocios en España. Más sobre mí →
¿Necesitas desarrollo a medida?
Desarrollo funcionalidades específicas, integraciones entre sistemas y herramientas internas. Si se puede programar, probablemente puedo hacerlo.