🧶 yarn: El Orden del Monorepo y la Estabilidad
“El clan ninja no es un guerrero solitario. Es una red coordinada donde cada miembro conoce su lugar.” - Código del Trabajo Coordinado
🎯 ¿Qué es yarn y por qué existe?
yarn fue creado por Facebook en 2016 para resolver problemas críticos de npm (en ese momento):
- Lentitud: Instalaciones tardaban minutos
- No determinismo: Diferentes instalaciones producían diferentes versiones
- Sin lockfile: No había forma de garantizar reproducibilidad
- Sin soporte para monorepos: Difícil gestionar múltiples paquetes relacionados
Hoy (2026):
- npm mejoró enormemente (lockfile, velocidad)
- yarn sigue siendo relevante por workspaces y estabilidad
- yarn v1 (classic) vs yarn v2+ (Berry) son ecosistemas diferentes
Instalación:
# Con npm
npm install -g yarn
# Con Homebrew (macOS)
brew install yarn
# Verificar instalación
yarn --version
📜 Comandos Básicos
yarn usa sintaxis similar a npm pero más concisa:
Instalar Paquetes
# Instalar dependencia (NO necesitas 'install')
yarn add express
# Instalar devDependency
yarn add -D jest
# Instalar versión específica
yarn add react@18.2.0
# Instalar globalmente
yarn global add typescript
Eliminar Paquetes
yarn remove lodash
Actualizar Paquetes
# Ver paquetes desactualizados
yarn outdated
# Actualizar todos (interactivo)
yarn upgrade-interactive
# Actualizar uno específico
yarn upgrade react
# Actualizar a última versión (ignorar rangos)
yarn upgrade react@latest
Instalar Desde package.json
# Instalar todo (clonar proyecto)
yarn install
# Atajo (solo 'yarn' es suficiente)
yarn
# Instalar solo producción
yarn install --production
Ejecutar Scripts
# NO necesitas 'run'
yarn dev
yarn build
yarn test
🔒 yarn.lock: La Garantía de Reproducibilidad
El archivo yarn.lock registra las versiones exactas de TODAS las dependencias.
Diferencia con npm:
| Aspecto | npm (package-lock.json) | yarn (yarn.lock) |
|---|---|---|
| Formato | JSON | YAML-like custom |
| Legibilidad | Difícil (generado) | Más legible |
| Merge conflicts | Frecuentes | Menos frecuentes |
| Generación | Automática | Automática |
Ejemplo de yarn.lock:
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
Reglas de oro:
- ✅ SÍ versiona
yarn.locken Git - ❌ NO lo edites manualmente
- ✅ Commitea cambios en
yarn.lockjunto conpackage.json
🏢 Workspaces: El Superpoder de yarn
Workspaces permiten gestionar múltiples paquetes en un solo repositorio (monorepo).
Cuándo Usar Monorepos
✅ Sí usa monorepo si:
- Tienes paquetes relacionados (app web + app móvil + librería compartida)
- Compartes código entre proyectos
- Quieres hacer cambios atómicos (un commit afecta varios paquetes)
❌ No uses monorepo si:
- Proyectos completamente independientes
- Equipos separados sin código compartido
Configurar Workspaces
Estructura de directorios:
mi-monorepo/
├── packages/
│ ├── web-app/
│ │ ├── package.json
│ │ └── src/
│ ├── mobile-app/
│ │ ├── package.json
│ │ └── src/
│ └── shared-components/
│ ├── package.json
│ └── src/
├── package.json ← Root package
└── yarn.lock
Root package.json:
{
"name": "mi-monorepo",
"private": true,
"workspaces": [
"packages/*"
]
}
Packages individuales:
// packages/web-app/package.json
{
"name": "web-app",
"version": "1.0.0",
"dependencies": {
"react": "^18.2.0",
"shared-components": "1.0.0" ← Referencia interna
}
}
// packages/shared-components/package.json
{
"name": "shared-components",
"version": "1.0.0",
"dependencies": {
"react": "^18.2.0"
}
}
Instalar Dependencias en Monorepo
# Desde la raíz, instala TODAS las dependencias de todos los workspaces
yarn install
Qué sucede:
- yarn lee
workspacesen rootpackage.json - Encuentra todos los
package.jsonenpackages/* - Instala dependencias en un solo
node_modules/en la raíz - Enlaza paquetes internos automáticamente
Resultado:
mi-monorepo/
├── node_modules/ ← UN SOLO node_modules
│ ├── react/
│ ├── shared-components → packages/shared-components (symlink)
│ └── ...
├── packages/
│ ├── web-app/
│ └── shared-components/
Añadir Dependencia a un Workspace Específico
# Añadir axios solo a web-app
yarn workspace web-app add axios
# Añadir jest a mobile-app como devDependency
yarn workspace mobile-app add -D jest
Ejecutar Scripts en Workspaces
# Ejecutar dev en web-app
yarn workspace web-app dev
# Ejecutar test en todos los workspaces
yarn workspaces run test
# Ejecutar build en todos
yarn workspaces run build
🔍 yarn vs npm vs pnpm
| Característica | npm | yarn | pnpm |
|---|---|---|---|
| Velocidad | Media | Alta | Muy alta |
| Espacio disco | Alto | Alto | Muy bajo |
| Workspaces | Sí (v7+) | Sí (nativo) | Sí (nativo) |
| Lockfile | package-lock.json | yarn.lock | pnpm-lock.yaml |
| Sintaxis | npm install | yarn add | pnpm add |
| Popularidad | Muy alta | Alta | Creciente |
| Curva aprendizaje | Baja | Baja | Baja |
Cuándo Usar Cada Uno
Usa npm si:
- Equipo usa npm (convención)
- Proyecto simple sin monorepo
- Siguiendo tutoriales (mayoría usa npm)
Usa yarn si:
- Trabajas en monorepo
- Quieres instalaciones determinísticas
- Tu equipo ya lo usa (React, Next.js lo usan internamente)
Usa pnpm si:
- Espacio en disco es crítico
- Múltiples proyectos en tu máquina
- Quieres máxima velocidad
⚡ Comandos Avanzados de yarn
Verificar Integridad
# Verificar que node_modules coincide con yarn.lock
yarn check
# Verificar checksums de paquetes
yarn check --integrity
Limpiar Caché
# Ver ubicación de caché
yarn cache dir
# Limpiar caché
yarn cache clean
Listar Dependencias
# Ver árbol de dependencias
yarn list
# Solo nivel 0 (directas)
yarn list --depth=0
# Ver de dónde viene un paquete
yarn why lodash
Upgrade Interactivo
# Seleccionar qué paquetes actualizar (UI interactiva)
yarn upgrade-interactive --latest
Auditar Seguridad
# Buscar vulnerabilidades
yarn audit
# Intentar arreglarlas
yarn audit fix
💡 yarn v1 (Classic) vs yarn v2+ (Berry)
yarn Classic (v1.x)
- Versión tradicional (2016-2020)
- Compatible con npm
- Usa
node_modules/normal - Recomendado para principiantes
yarn Berry (v2+)
- Reescritura completa (2020+)
- Modo Plug’n’Play (PnP): Sin
node_modules/ - Más rápido pero menos compatible
- Solo para expertos
Verificar qué versión tienes:
yarn --version
# 1.22.x = Classic
# 3.x.x = Berry
Migrar a Berry (opcional):
yarn set version berry
⚠️ No recomendado para principiantes: Berry tiene incompatibilidades con muchas herramientas.
🎯 Ejemplo Real: Monorepo con yarn
Caso de Uso
Tienes:
- Frontend (React)
- Backend (Node.js)
- Librería compartida de utilidades
Configuración
1. Crear estructura:
mkdir ninja-monorepo
cd ninja-monorepo
yarn init -y
2. Configurar workspaces en package.json:
{
"name": "ninja-monorepo",
"private": true,
"workspaces": [
"packages/*"
]
}
3. Crear paquetes:
mkdir -p packages/{frontend,backend,shared}
# Frontend
cd packages/frontend
yarn init -y
yarn add react react-dom
# Backend
cd ../backend
yarn init -y
yarn add express
# Shared
cd ../shared
yarn init -y
4. Enlazar paquetes:
// packages/frontend/package.json
{
"dependencies": {
"react": "^18.2.0",
"shared": "1.0.0" ← Workspace interno
}
}
5. Instalar todo:
# Desde la raíz
cd ../..
yarn install
6. Ejecutar scripts:
yarn workspace frontend start
yarn workspace backend dev
🎯 Reto Ninja del Tema
Misión: Crear tu primer monorepo con yarn
-
Inicializa monorepo:
mkdir yarn-dojo cd yarn-dojo yarn init -y -
Configura workspaces en
package.json:{ "private": true, "workspaces": ["packages/*"] } -
Crea dos paquetes:
mkdir -p packages/{app,utils} cd packages/utils yarn init -y # Crea src/index.js con una función simple cd ../app yarn init -y -
Enlaza utils en app:
// packages/app/package.json { "dependencies": { "utils": "1.0.0" } } -
Instala:
cd ../.. yarn install -
Usa el paquete compartido:
// packages/app/index.js const { suma } = require('utils'); console.log(suma(2, 3));
Criterios de éxito:
- ✅ Creaste un monorepo funcional
- ✅ Enlazaste paquetes internos
- ✅ Instalaste en un solo
node_modules/ - ✅ Ejecutaste código compartido entre paquetes
⚠️ Errores Comunes
Error #1: Workspaces no detectados
error Couldn't find any versions for "mi-paquete"
Causa: package.json root no tiene "private": true
Solución:
{
"private": true,
"workspaces": ["packages/*"]
}
Error #2: Versiones incompatibles
error Incompatible peer dependencies
Solución:
# Forzar instalación (usar con precaución)
yarn install --ignore-engines
Error #3: yarn.lock en conflicto (Git)
Solución:
# Eliminar yarn.lock conflictivo
rm yarn.lock
# Regenerar desde package.json
yarn install
📚 Recursos Adicionales
Siguiente Pergamino: 4.7 package.json, Scripts y Semver
¿Creaste tu monorepo? Comparte tu estructura en Discord con #yarnNinja! 🧶🥷