Gestiona tu Monorepo con Turborepo

3 min

1. ¿Por qué elegir un Monorepo?

Un Monorepo, o repositorio de código único, es una estrategia que almacena varios proyectos o paquetes independientes en un mismo repositorio. Frente al modelo Polyrepo, donde cada proyecto tiene su propio repositorio, un Monorepo ofrece varias ventajas destacadas:

  • Código compartido: Compartir componentes, funciones auxiliares o definiciones de tipos entre distintos proyectos resulta muy sencillo.
  • Commits atómicos: Si el cambio de una función afecta a varios paquetes, puede completarse en un solo commit, lo que garantiza la coherencia de las versiones.
  • Gestión de dependencias simplificada: Todos los proyectos comparten un mismo node_modules, o lo optimizan mediante workspaces de pnpm/yarn, reduciendo conflictos de dependencias y diferencias entre versiones.

Sin embargo, cuando el repositorio crece, el Monorepo también presenta un desafío: el rendimiento de compilación.

2. Los puntos débiles de un Monorepo

Imagina que tu repositorio contiene docs, webapp y una biblioteca compartida de componentes ui. Si solo corriges un error tipográfico en docs, lo último que quieres es que todos los proyectos del repositorio, incluidos webapp y ui, vuelvan a compilarse y probarse.

Las herramientas tradicionales de gestión de Monorepos, como Lerna, presentan limitaciones en la coordinación de tareas y la caché de compilación, lo que provoca:

  • Trabajo repetido: Cada ejecución de CI/CD compila y prueba todo desde cero, aunque la mayor parte del código no haya cambiado.
  • Tiempos de compilación largos: No se pueden aprovechar eficazmente varios núcleos de CPU para ejecutar tareas en paralelo.
  • Scripts complejos: Es necesario escribir scripts complicados en package.json para controlar manualmente el orden de ejecución de las tareas.

3. Turborepo: creado para la velocidad

Turborepo es un sistema de compilación de alto rendimiento diseñado para Monorepos JavaScript/TypeScript y adquirido posteriormente por Vercel. Resuelve los problemas anteriores mediante dos tecnologías fundamentales: las compilaciones incrementales y la caché remota.

a. Compilaciones incrementales y pipelines de tareas

Turborepo permite definir las dependencias entre tareas en un archivo turbo.json situado en la raíz.

// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": []
    },
    "lint": {
      "outputs": []
    },
    "dev": {
      "cache": false
    }
  }
}
  • dependsOn: ["^build"]: El símbolo ^ indica que la tarea build de un paquete depende de las tareas build de todos los paquetes de los que depende. Turborepo ejecuta las tareas en el orden paralelo más eficiente de acuerdo con este grafo.
  • outputs: Indica a Turborepo qué archivos de salida produce la tarea.

Cuando ejecutas pnpm turbo build, Turborepo calcula qué archivos han cambiado y solo vuelve a compilar los paquetes afectados. Si el código fuente y las dependencias de un paquete no han cambiado, Turborepo utiliza directamente el resultado de la compilación anterior, un proceso instantáneo.

b. Caché remota

Esta es la «función estrella» de Turborepo. No solo almacena en caché los resultados de compilación en tu equipo local, sino que también puede subirlos a un servidor remoto compartido, como Vercel o tu propio bucket de S3.

Esto significa que:

  • Tu compañero puede descargar la caché después de obtener el código más reciente si tú ya has compilado la parte que necesita, sin tener que volver a compilarla localmente.
  • El servidor de CI/CD también puede conectarse a esta caché remota. Después de que un PR se compile y almacene en caché dentro de CI, otros desarrolladores y tareas posteriores de CI podrán aprovechar el resultado de inmediato.

Esto puede reducir el tiempo de compilación de todo el equipo de decenas de minutos a unos pocos minutos o incluso decenas de segundos.

Conclusión

Turborepo no inventó el Monorepo, pero al introducir sistemas avanzados de caché y planificación de tareas mejora enormemente la experiencia de desarrollo en un Monorepo y resuelve su principal cuello de botella de rendimiento. Si utilizas o piensas adoptar una arquitectura Monorepo, Turborepo es sin duda una herramienta potente que puede ahorrar muchísimo tiempo a ti y a tu equipo.