Monorepos
Estrategia de organización de código donde múltiples proyectos coexisten en un único repositorio, compartiendo dependencias, configuración y herramientas de build.
Un monorepo es un repositorio único que contiene múltiples proyectos distintos con relaciones bien definidas entre ellos. No es simplemente «todo el código en una carpeta» — es una estrategia arquitectónica con herramientas especializadas.
¿Qué problema resuelve?
En un modelo polyrepo (un repositorio por proyecto), los equipos enfrentan:
- Dependency hell — sincronizar versiones entre repos es manual y propenso a errores
- Cambios atómicos imposibles — un refactor que toca 3 repos requiere 3 PRs coordinados
- Duplicación de configuración — ESLint, TypeScript, CI/CD copiados en cada repo
- Descubrimiento difícil — ¿dónde está el código que necesito? ¿qué versión usa el otro equipo?
El monorepo centraliza todo en un solo lugar con herramientas que manejan la complejidad.
¿Cuándo usarlo?
Buena opción cuando:
- Múltiples paquetes comparten código común (tipos, utilidades, componentes)
- El equipo necesita hacer cambios atómicos que cruzan boundaries
- Quieres una sola fuente de verdad para configuración (linting, testing, CI)
- Los proyectos tienen ciclos de release coordinados
Evitar cuando:
- Proyectos completamente independientes sin código compartido
- Equipos con ciclos de release muy diferentes
- Restricciones de acceso estrictas (el monorepo implica visibilidad compartida)
- El repo crecería a tamaños que Git no maneja bien (>10GB, millones de archivos)
Herramientas principales
| Herramienta | Enfoque | Lenguaje | Características clave |
|---|---|---|---|
| Turborepo | Build caching | JS/TS | Caché remoto, pipelines declarativos, zero-config |
| Nx | Full-featured | JS/TS | Generators, affected commands, graph visualization |
| pnpm workspaces | Package manager | JS/TS | Symlinks eficientes, strict dependencies |
| Lerna | Publishing | JS/TS | Versioning coordinado, changelogs (ahora parte de Nx) |
| Bazel | Hermetic builds | Políglota | Reproducibilidad, escalabilidad extrema (Google-scale) |
| Pants | Hermetic builds | Python/Go/Java | Similar a Bazel, mejor DX |
| Rush | Enterprise | JS/TS | Políticas estrictas, phantom dependencies detection |
Turborepo vs Nx
La comparación más común en el ecosistema JavaScript:
Turborepo — minimalista, se integra con tu setup existente, excelente caché remoto con Vercel. Ideal si ya tienes un monorepo y quieres acelerar builds sin cambiar mucho.
Nx — más opinionado, incluye generators para scaffolding, plugins para frameworks específicos, visualización de dependencias. Mejor si empiezas de cero o quieres estructura guiada.
Estructura típica
monorepo/
├── apps/
│ ├── web/ # Next.js app
│ ├── mobile/ # React Native app
│ └── api/ # Backend service
├── packages/
│ ├── ui/ # Shared components
│ ├── utils/ # Shared utilities
│ └── config/ # Shared ESLint, TS configs
├── turbo.json # Pipeline configuration
├── pnpm-workspace.yaml
└── package.json
Patrones clave
1. Internal packages
Paquetes que nunca se publican a npm — solo se consumen dentro del monorepo:
{
"name": "@repo/ui",
"private": true,
"exports": {
".": "./src/index.ts"
}
}2. Task pipelines
Definir dependencias entre tareas para paralelización correcta:
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"]
}
}
}3. Caché remoto
El build de un paquete que no cambió se recupera del caché en lugar de re-ejecutarse:
# Primera vez: ejecuta build
turbo build # 45s
# Segunda vez (sin cambios): recupera del caché
turbo build # 0.3sAnti-patrones
- Monolito disfrazado — todo en un repo pero sin boundaries claros entre paquetes
- Caché sin invalidación correcta — builds que no detectan cambios en dependencias
- Circular dependencies — paquete A importa B que importa A
- God package — un
@repo/utilsque crece sin control y todos dependen de él
Este sitio es un monorepo
jonmatum.com usa Turborepo + pnpm workspaces con apps/web (Next.js) y packages/knowledge (pipeline de contenido). El caché de Turborepo reduce el build de ~45s a menos de 1s cuando solo cambia contenido MDX.
¿Por qué importa?
La decisión entre monorepo y polyrepo afecta la velocidad de desarrollo, la complejidad del CI/CD y la capacidad de compartir código entre equipos. No hay respuesta universal — pero entender los trade-offs evita meses de migración dolorosa cuando la elección inicial no escala.
Referencias
- Monorepo Explained — Nrwl, 2023. Comparativa exhaustiva de herramientas y patrones.
- Turborepo Handbook — Vercel, 2024. Guía oficial con mejores prácticas.
- Why Google Stores Billions of Lines of Code in a Single Repository — Google Research, 2016. El paper seminal sobre monorepos a escala.
- Monorepos: Please don't! — Matt Klein, 2019. Perspectiva crítica sobre cuándo evitarlos.