¿Qué es Turborepo?
Turborepo es un sistema de construcción de alto rendimiento para monorepos de JavaScript. Ejecuta tareas en todos los paquetes de tu repositorio, respeta el orden de dependencias entre ellos y almacena los resultados en caché para que el trabajo que no ha cambiado nunca se repita.
Un monorepo sin un sistema de construcción se vuelve problemático rápidamente. Ejecutar build y test manualmente en cada paquete es lento, y un script ingenuo vuelve a ejecutar todo incluso cuando solo ha cambiado un paquete. Turborepo resuelve ambos problemas: un pipeline de tareas declarativo gestiona el orden, y el hashing basado en contenido hace que las tareas sin cambios sean efectivamente gratuitas.
El pipeline de tareas
El pipeline se encuentra en turbo.json. Cada tarea declara sus dependencias y sus salidas (outputs).
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
},
"lint": {},
"dev": {
"cache": false,
"persistent": true
}
}
}
dependsOn con un acento circunflejo (^build) significa “construye primero mis dependencias”. Sin el acento, se refiere a una tarea dentro del mismo paquete. outputs le indica a Turborepo qué debe cachear, y cache: false excluye una tarea como dev porque se ejecuta indefinidamente.
Ejecución de tareas
Un solo comando ejecuta una tarea en todo el repositorio, en el orden correcto y en paralelo siempre que sea posible.
turbo run build
turbo run test lint
turbo run dev --filter=web
Turborepo construye un grafo a partir de dependsOn, ejecuta las tareas independientes de forma concurrente y pone en cola aquellas que tienen dependencias. El resultado es la programación más rápida posible que sigue respetando las restricciones entre los paquetes.
Caching
El caching es la funcionalidad que transforma la experiencia de trabajar en un monorepo. Para cada tarea, Turborepo genera un hash de los inputs —archivos fuente, dependencias, variables de entorno y configuración— y almacena los outputs y logs asociados a ese hash.
En la siguiente ejecución, si el hash no ha cambiado, la tarea se omite y sus outputs se restauran desde el cache. Los logs también se reproducen, por lo que el resultado se ve igual sin que se haya tenido que realizar el trabajo. Con un cache caliente, un turbo run build completo a través de docenas de paquetes puede finalizar en segundos.
Caching remoto
Un caché local solo ayuda a una máquina. El caching remoto comparte el caché entre todo el equipo y la CI.
- Un desarrollador compila un paquete; el resultado se sube al servidor.
- Otro desarrollador descarga el mismo commit y lo restaura al instante.
- La CI restaura los mismos artefactos, omitiendo el trabajo que ya se ha realizado en otro lugar.
Esto convierte al caché en un activo compartido y suele ser la mejora de velocidad más significativa para la CI en un monorepo. Vercel ofrece un servicio de caching remoto gestionado, y existen opciones self-hosted para los equipos que las necesiten.
Filtrado
Rara vez es necesario ejecutar todas las tareas en monorepos grandes. El filtrado permite dirigirse a un subconjunto de paquetes.
# only packages affected by changes since main
turbo run test --filter="...[origin/main]"
# one package and its dependencies
turbo run build --filter=web...
# only packages that depend on @repo/ui
turbo run build --filter=...@repo/ui
La sintaxis [origin/main] le indica a Turborepo que calcule qué paquetes han cambiado e incluya sus dependientes. En CI, esto significa que un pull request que afecte a un solo paquete solo construirá y probará aquello que realmente pueda verse afectado.
Workspaces y estructura
Turborepo no gestiona las dependencias por sí mismo; esa es tarea del gestor de paquetes. Tú defines los workspaces con pnpm, npm, yarn o bun, y Turborepo añade la capa de pipeline y caché encima.
repo/
├── apps/
│ ├── web/ # a deployable app
│ └── docs/
├── packages/
│ ├── ui/ # a shared component library
│ └── config/ # shared config
├── package.json
├── pnpm-workspace.yaml
└── turbo.json
Las aplicaciones consumen paquetes compartidos a través del protocolo de workspace, y Turborepo comprende ese grafo de dependencias al ordenar las tareas. La combinación de pnpm workspaces para el enlace y Turborepo para la ejecución de tareas es la configuración de monorepo moderno más común.
Mejores prácticas
- Declara
outputspara cada tarea que pueda almacenarse en caché. - Usa
dependsOncon^para expresar el orden de las dependencias. - Marca las tareas de larga duración, como
dev, concache: false. - Habilita el remote caching en CI para obtener las mayores mejoras de rendimiento.
- Filtra por paquetes modificados en CI para mantener los pipelines rápidos.
- Mantén
turbo.jsonen la raíz del repositorio y compártelo entre los paquetes. - Añade un script en la raíz para que todo el equipo ejecute los mismos comandos.
Errores comunes
- Olvidar
outputsy perder el beneficio de la caché. - Ejecutar tareas en un orden arbitrario en lugar de usar
dependsOn. - Cachear una tarea persistente, como un servidor de desarrollo.
- Incluir variables de entorno volátiles en el hash innecesariamente.
- Ejecutar el pipeline completo en CI cuando el filtrado omitiría los paquetes no afectados.
- Tratar Turborepo como un reemplazo de un gestor de paquetes.
Próximos pasos
Turborepo transforma un monorepo de ser una carga a ser una ventaja. Combínalo con pnpm para el enlace de workspaces, comprende los fundamentos de npm y Node.js, y mantén la construcción de los paquetes individuales con Vite. Después, añade un turbo run build en la raíz de un repositorio que tenga más de un paquete y observa cómo la segunda ejecución termina casi instantáneamente.