Turborepo para Node
Turborepo orquesta las tareas del espacio de trabajo con caché remota para que los paquetes sin cambios omitan las reconstrucciones en CI y localmente.
Receta
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": []
},
"typecheck": {
"dependsOn": ["^build"],
"outputs": []
}
}
}npx turbo run build test typecheckCuándo usarlo:
- Monorepo con más de 3 paquetes y
build/testrepetidos en CI. - Las bibliotecas compartidas deben compilarse antes de que las aplicaciones realicen la verificación de tipos.
- Quieres aciertos de caché entre desarrolladores y ejecutores de CI.
Ejemplo de trabajo
platform/
turbo.json
package.json # workspaces
apps/
api/package.json
packages/
shared/package.json
// package.json (root)
{
"private": true,
"workspaces": ["apps/*", "packages/*"],
"scripts": {
"build": "turbo run build",
"test": "turbo run test",
"dev": "turbo run dev --parallel"
},
"devDependencies": {
"turbo": "^2.3.0",
"typescript": "^5.6.0"
}
}// packages/shared/package.json
{
"name": "@acme/shared",
"scripts": {
"build": "tsc -p tsconfig.json",
"test": "node --import tsx --test"
}
}// apps/api/package.json
{
"name": "@acme/api",
"dependencies": { "@acme/shared": "workspace:*", "fastify": "^5.0.0" },
"scripts": {
"build": "tsc -p tsconfig.json",
"dev": "tsx watch src/server.ts",
"test": "node --import tsx --test"
}
}npm install
npx turbo run build --filter=@acme/api...Lo que esto demuestra:
^buildejecuta las compilaciones de paquetes de dependencia antes que los dependientes.--filter=@acme/api...incluye la API y sus dependencias del espacio de trabajo.outputsle dice a Turbo qué almacenar en caché entre ejecuciones.
Análisis profundo
Cómo funciona
- Turbo hash los inputs de la tarea (código fuente, variables de entorno, dependencias) y restaura
outputsdel caché en caso de acierto. dependsOnconstruye un DAG;testespera los artefactos debuild.- La caché remota (Vercel o autoalojada) comparte los aciertos entre las máquinas de CI.
- Las tareas
devsuelen serpersistent: truey no se almacenan en caché.
Configuración de tareas
| Campo | Propósito |
|---|---|
dependsOn | Orden de tareas ascendentes (^build = dependencias primero) |
outputs | Carpetas restauradas del caché (dist/**) |
inputs | Ajustar el hash (predeterminado: archivos de paquete) |
env | Variables de entorno que invalidan la caché cuando cambian |
Notas de TypeScript
{
"tasks": {
"build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
"typecheck": { "dependsOn": ["^build"] }
}
}- Separa
typecheckdebuildsi quieres trabajos de CI más rápidos que omitan la emisión al verificar solo los tipos. - Asegúrate de que cada
tsconfigdel paquete emita adist/de forma consistente para las rutas de caché.
Errores comunes
outputsfaltantes - Turbo no almacena nada útil en caché; cada compilación se vuelve a ejecutar por completo. Solución: declaradist/**por tarea de compilación.- Sintaxis de filtro incorrecta -
@acme/apisolo omite las compilaciones de dependencia. Solución: usa@acme/api...(tres puntos) para la cadena de dependientes. - Pruebas de caché con efectos secundarios - Las pruebas que acceden a una base de datos real obtienen un falso positivo del caché. Solución: excluye las pruebas de integración de las tareas cacheadas o usa
inputsúnicos. - Secretos de entorno en el hash - Las listas
envinvalidan la caché cuando cambian los tokens. Solución: solo lista las variables de entorno que afectan la salida de la compilación. - Tarea
devcacheadas por error - El modo de observación no debe almacenar en caché. Solución:"persistent": truey sinoutputsendev.
Alternativas
| Alternativa | Usar cuándo | No usar cuándo |
|---|---|---|
Scripts npm run -w solamente | Monorepo de 2 paquetes | El tiempo de CI crece linealmente con los paquetes |
| Nx | Generadores, grafo afectado, cumplimiento | El equipo quiere una configuración mínima |
| Bazel | Repositorios políglotas enormes | Tienda de backend solo de Node |
Preguntas frecuentes
¿Turbo reemplaza los workspaces de npm?
No. Turbo se ejecuta sobre los workspaces. Sigues usando npm ci y el enlace workspace:*.
¿Cómo ejecuto una aplicación en desarrollo?
npx turbo run dev --filter=@acme/apiAñade --parallel cuando ejecutes varios servidores de desarrollo.
¿Qué deben incluir los outputs?
dist/** compilado, especificaciones OpenAPI generadas o *.tsbuildinfo si almacenas en caché compilaciones incrementales.
¿Cómo funciona la autenticación de caché remota?
turbo login y TURBO_TOKEN en CI. Autoalojado con almacenamiento compatible con S3 para equipos sin conexión a la red.
¿Pueden coexistir las aplicaciones Express y Fastify?
Sí, en espacios de trabajo apps/* separados. El código compartido reside en packages/ sin importaciones de frameworks.
¿Debería la prueba depender de la compilación?
Sí, cuando las pruebas importan dist/ o tipos compilados. Las pruebas de código fuente tsx puro pueden omitir la dependencia de compilación si se configuran cuidadosamente.
¿Cómo invalido la caché después de una actualización de la cadena de herramientas?
Cambiar el package-lock.json raíz o turbo.json invalida los hashes globalmente para las tareas afectadas.
¿Es necesario turbo para una sola API?
No. Añádelo cuando aparezca un segundo paquete o servicio y la CI exceda ~5 minutos regularmente.
¿Cómo usan las compilaciones de Docker Turbo?
Ejecuta turbo prune --scope=@acme/api --docker para generar un subconjunto mínimo para imágenes de varias etapas.
¿Un monorepo de NestJS usa Turbo?
Nest tiene su propio modo de monorepo; muchos equipos aún añaden Turbo para bibliotecas packages/ entre frameworks.
Relacionado
- Workspaces y Monorepos - enlace de workspaces
- Monorepo de múltiples servicios - límites desplegables
- Nx para backends de Node - orquestación alternativa
Versiones de la pila: Esta página fue escrita para Node.js 24.18.0 (LTS activa), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 y NestJS 11.