pnpm vs npm vs yarn: por qué uso pnpm
Comparativa práctica entre los tres package managers más populares. Velocidad, espacio en disco y por qué pnpm es mi elección.
Después de años usando npm y yarn, cambié a pnpm hace un tiempo y no he vuelto atrás. En este post te explico las diferencias reales y por qué pnpm se ha convertido en mi package manager por defecto.
Comparativa rápida
| Característica | npm | yarn | pnpm |
|---|---|---|---|
| Velocidad | Lento | Rápido | Muy rápido |
| Espacio en disco | Alto (duplica deps) | Alto | Bajo (symlinks) |
| node_modules | Desordenado | Desordenado | Organizado |
| Monorepos | Workspaces | Workspaces | Workspaces nativos |
| Lockfile | package-lock.json | yarn.lock | pnpm-lock.yaml |
| Instalación | Incluido con Node | npm i -g yarn | npm i -g pnpm |
El problema con npm y yarn
Duplican todo
Imagina que tienes 10 proyectos que usan React 19. Con npm o yarn:
proyecto-1/node_modules/react/ → 2.5 MB
proyecto-2/node_modules/react/ → 2.5 MB
proyecto-3/node_modules/react/ → 2.5 MB
...
proyecto-10/node_modules/react/ → 2.5 MB
Total: 25 MB solo para React
Cada proyecto tiene su propia copia. Multiplica esto por todas tus dependencias y proyectos... fácilmente llegas a varios GB desperdiciados.
Permiten importar cosas que no instalaste
npm y yarn mezclan todas las dependencias en node_modules, incluyendo las dependencias de tus dependencias. Esto causa un problema:
// Tu package.json NO tiene "lodash"
// Pero react-scripts sí lo usa internamente
import _ from 'lodash'; // ¡Funciona! (pero no debería)
Esto se llama "dependencia fantasma". Tu código funciona hoy, pero si mañana react-scripts deja de usar lodash, tu app se rompe sin que hayas tocado nada.
Cómo pnpm resuelve esto
Content-addressable store
pnpm guarda todas las dependencias en un store global (~/.pnpm-store). Cada versión de cada paquete existe una sola vez:
~/.pnpm-store/
├── react@19.0.0/
├── react@18.3.1/
├── typescript@5.8.0/
└── ...
Tus proyectos usan symlinks (enlaces simbólicos) a este store:
proyecto-1/node_modules/react → ~/.pnpm-store/react@19.0.0
proyecto-2/node_modules/react → ~/.pnpm-store/react@19.0.0
10 proyectos con React 19 = 2.5 MB total (no 25 MB). El ahorro de espacio es brutal.
Solo puedes usar lo que instalaste
pnpm organiza node_modules de forma que solo puedes importar lo que está en tu package.json. Si intentas usar una dependencia fantasma:
import _ from 'lodash'; // ❌ Error: Cannot find module 'lodash'
pnpm te obliga a instalarla explícitamente:
pnpm add lodash
Ahora sí funciona, y queda documentado en tu package.json. Nada de sorpresas.
Velocidad real
Hice un benchmark instalando las dependencias de un proyecto React típico:
# Proyecto con ~50 dependencias
npm install → 45 segundos
yarn install → 28 segundos
pnpm install → 12 segundos
La primera instalación de pnpm puede ser similar a npm (tiene que poblar el store). Las siguientes son mucho más rápidas porque reutiliza la caché.
Instalación
# Con npm
npm install -g pnpm
# Con Homebrew (macOS)
brew install pnpm
# Con corepack (recomendado, viene con Node 16+)
corepack enable
corepack prepare pnpm@latest --activate
Verifica la instalación:
pnpm --version
Comandos equivalentes
| npm | yarn | pnpm |
|---|---|---|
npm install | yarn | pnpm install |
npm install pkg | yarn add pkg | pnpm add pkg |
npm install -D pkg | yarn add -D pkg | pnpm add -D pkg |
npm uninstall pkg | yarn remove pkg | pnpm remove pkg |
npm run dev | yarn dev | pnpm dev |
npx create-next-app | yarn create next-app | pnpm create next-app |
npx pkg | yarn dlx pkg | pnpm dlx pkg |
pnpm install instala todas las dependencias del package.json. pnpm add pkg agrega un paquete nuevo al proyecto.
Son comandos diferentes, no intercambiables.
Migrar de npm/yarn a pnpm
Es simple:
# 1. Elimina node_modules y lockfile anterior
rm -rf node_modules package-lock.json yarn.lock
# 2. Instala con pnpm
pnpm install
Esto genera pnpm-lock.yaml. Commitea este archivo y elimina el lockfile anterior de git.
Configuración útil
Crea un archivo .npmrc en tu proyecto:
# Usa la versión exacta de Node especificada
use-node-version=20.11.0
# Auto-instala peer dependencies
auto-install-peers=true
# Modo estricto (recomendado)
strict-peer-dependencies=false
¿Cuándo NO usar pnpm?
Hay algunos casos donde podrías tener problemas:
- Proyectos legacy que dependen de poder importar dependencias no declaradas
- Algunas herramientas que no manejan bien symlinks (cada vez menos común)
- CI/CD donde no tienes control de la caché (aunque pnpm tiene opciones para esto)
La mayoría de proyectos modernos funcionan perfecto con pnpm. Si encuentras un problema, usualmente es una dependencia mal configurada que eventualmente también fallaría con npm/yarn.
Conclusión
pnpm no es solo "otro package manager". Resuelve problemas reales:
- Ahorra espacio → Un store global con symlinks
- Es más rápido → Instalaciones paralelas y caché eficiente
- Es más seguro → No puedes importar dependencias fantasma
- Monorepos nativos → Sin configuración extra
Si todavía usas npm o yarn, dale una oportunidad a pnpm. La migración es simple y los beneficios son inmediatos.