¿Qué es pnpm?
pnpm es un gestor de paquetes que almacena cada versión de cada paquete una sola vez en un almacén direccionable por contenido (content-addressable store) global y crea enlaces físicos (hard-links) hacia cada proyecto que lo necesite. El resultado es un uso de disco drásticamente menor e instalaciones mucho más rápidas, especialmente cuando se manejan muchos proyectos o un monorepo.
También es estricto. En lugar de aplanar cada dependencia en un único node_modules, pnpm utiliza enlaces simbólicos (symlinks) que reflejan el grafo de dependencias real. Un paquete solo puede importar aquello que declara explícitamente, por lo que la dependencia accidental de una dependencia transitiva falla inmediatamente en lugar de funcionar localmente y romperse en producción.
El store y node_modules
El store reside en un directorio global y contiene el contenido de cada versión de paquete que hayas instalado. Cuando un proyecto necesita un paquete, pnpm crea un hard-link desde el store en lugar de copiarlo.
El diseño de node_modules utiliza entonces symlinks:
node_modules/.pnpmcontiene los paquetes reales.node_modules/<name>enlaza a la versión que declaró tu proyecto.- El
node_modulesde cada paquete enlaza únicamente a sus dependencias declaradas.
Es por esto que pnpm detecta las dependencias fantasma: si tu código importa un paquete que olvidaste añadir a package.json, fallará, ya que el paquete no está enlazado en el nivel superior. El diseño plano de npm a menudo permite que ese error pase desapercibido.
Comandos
Los comandos son muy similares a los de npm, lo que facilita la migración.
pnpm install # install from the lockfile
pnpm add zod # add a dependency
pnpm add -D vitest # add a dev dependency
pnpm remove zod # remove a dependency
pnpm run build # run a script
pnpm dlx create-vite # run a package without installing
pnpm install utiliza el store, por lo que las instalaciones repetidas son rápidas. pnpm-lock.yaml cumple la misma función que package-lock.json y debe incluirse en el commit.
Workspaces
Los Workspaces son la característica estrella de pnpm. Declaras la ubicación de los paquetes en pnpm-workspace.yaml.
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"
Entonces, un workspace puede depender de otro paquete hermano utilizando el workspace protocol en lugar de una ruta de archivo relativa.
{
"name": "@repo/web",
"dependencies": {
"@repo/ui": "workspace:*"
}
}
pnpm enlaza el paquete local, y workspace:* se reemplaza por la versión real al publicar. Esto mantiene las dependencias internas explícitas y evita rutas file:../.. frágiles.
Catálogos y consistencia de versiones
En un monorepo grande, es común que diferentes paquetes dependan de distintas versiones de una misma librería. Los Catálogos centralizan esa decisión.
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"
catalog:
react: ^19.0.0
typescript: ^5.6.0
{
"dependencies": {
"react": "catalog:"
}
}
Cada paquete que utiliza catalog: resuelve a la versión definida una sola vez en la raíz, lo que convierte las actualizaciones en una edición única y evita la divergencia de versiones.
Filtrado y ejecución de tareas
pnpm puede dirigirse a un subconjunto de un workspace, lo cual es esencial en un monorepo.
# run tests only in packages that changed since main
pnpm --filter "...[origin/main]" test
# run a script in one package
pnpm --filter @repo/web dev
# run a script in every package
pnpm -r build
Los filtros admiten nombres de paquetes, globs de directorios y relaciones de dependencias, permitiéndote ejecutar un comando solo donde sea relevante. Para el almacenamiento en caché y la orquestación entre paquetes, combina pnpm con Turborepo, que está diseñado precisamente para esta configuración.
CI y reproducibilidad
Usa un lockfile congelado en CI para que la instalación falle si el lockfile y los manifiestos no coinciden.
pnpm install --frozen-lockfile
pnpm run build
Este es el equivalente en pnpm a npm ci y es lo que garantiza una build reproducible. Debido a que las instalaciones son rápidas y el store puede cachearse en CI, pnpm también tiende a reducir el tiempo del pipeline.
pnpm frente a npm
- Disco y velocidad: pnpm comparte los paquetes a través de un store y los enlaza; npm copia un árbol aplanado por proyecto.
- Estrictez: pnpm expone únicamente las dependencias declaradas; el diseño plano de npm permite importaciones fantasma (phantom imports).
- Workspaces: ambos los soportan, pero el protocolo de workspace y el filtrado de pnpm son más ergonómicos para monorepos grandes.
- Compatibilidad: ambos leen
package.jsony soportan el mismo registro, por lo que cambiar suele ser cuestión de borrarnode_modulesy el lockfile antiguo.
Elige npm por su simplicidad y ubicuidad, y pnpm cuando el espacio en disco, la velocidad o la ergonomía de los monorepos sean prioritarios. Consulta la guía de npm para conocer el flujo de trabajo predeterminado.
Mejores prácticas
- Haz commit de
pnpm-lock.yaml. - Usa
pnpm install --frozen-lockfileen CI. - Usa
workspace:*para dependencias internas. - Centraliza las versiones compartidas mediante catálogos.
- Aprovecha el modo estricto: añade las dependencias faltantes en lugar de desactivarlo.
- Usa
--filterpara ejecutar tareas solo donde sea necesario. - Combina pnpm con un task runner para gestionar el almacenamiento en caché en repositorios grandes.
Errores comunes
- Añadir dependencias en el nivel de workspace incorrecto con
-w. - Usar rutas
file:en lugar del protocolo de workspace. - Ignorar los errores de “not declared in package.json” en lugar de corregir el manifiesto.
- Olvidar
--frozen-lockfileen CI y obtener instalaciones no reproducibles. - Permitir que cada paquete fije su propia versión de una librería compartida.
- Mezclar gestores de paquetes en un mismo repositorio y crear lockfiles conflictivos.
Próximos pasos
pnpm es la opción más eficiente para proyectos modernos de JavaScript, especialmente para monorepos. Compáralo con npm, añade Turborepo para el almacenamiento en caché de tareas y comprende el runtime de Node.js que hay detrás. Después, pruébalo en un proyecto existente eliminando node_modules y dejando que pnpm reconstruya el árbol desde el store.