pnpm (Performant npm) es un reemplazo directo de npm con dos ideas clave: un store global en disco que solo guarda una copia de cada paquete, y una resolución estricta que evita las dependencias fantasma.
Por qué pnpm ahorra tanto espacio
Cuando haces npm install react, npm copia los archivos en tu-proyecto/node_modules/react/. Si tienes diez proyectos que usan React, tienes diez copias idénticas en el disco.
pnpm funciona de otra manera:
- Descarga React una sola vez en un store global (
~/.local/share/pnpm/storeen Linux/macOS,%LOCALAPPDATA%\pnpm\storeen Windows). - En cada proyecto,
node_modules/react/es un hardlink que apunta a los archivos del store. Un solo archivo físico, diez proyectos que acceden a él.
En concreto: en una máquina con diez proyectos React, npm ocupa ~400 MB por proyecto. pnpm ocupa ~40 MB (el store compartido) sin importar cuántos proyectos haya.
Instalar pnpm
Via npm (una sola vez):
Via corepack (incluido en Node desde v16):
Verifica:
Comandos habituales
Instalar todas las dependencias de un proyecto existente:
Añadir un paquete:
Añadir una devDependency:
Lanzar un script definido en package.json:
Atajo (sin run) para scripts habituales:
Ejecutar un comando puntual sin instalar globalmente:
Actualizar todas las dependencias:
Eliminar un paquete:
Resolución estricta: adiós a las dependencias fantasma
pnpm crea una estructura node_modules/ no aplanada. Cada paquete solo puede ver sus propias dependencias declaradas. Tu código no puede acceder a lodash si no has añadido lodash explícitamente a tu package.json.
Puede parecer restrictivo, pero es una garantía: tu build es reproducible y no depende de las dependencias transitivas de tus dependencias.
pnpm y los monorepos
pnpm tiene el mejor soporte de monorepos entre los tres gestores. Un archivo pnpm-workspace.yaml en la raíz es suficiente para declarar varios paquetes:
packages:
- "packages/*"
- "apps/*"Los paquetes del workspace pueden referenciarse entre sí con workspace:* como versión:
{
"dependencies": {
"@mi-proyecto/shared": "workspace:*"
}
}