pnpm
pnpm, el gestor de paquetes del equipo: instalación, comandos diarios, aprobación de builds, workspaces, configuración y CI.
- #pnpm
- #node
- #paquetes
- #monorepo
- #seguridad
Por qué pnpm
| Característica | Qué aporta |
|---|---|
| Store global con enlaces | Cada versión de un paquete se guarda una sola vez en disco y los proyectos la enlazan |
node_modules estricto | Solo puedes importar lo que declaras en package.json: adiós a las dependencias fantasma |
| Scripts bloqueados | preinstall, install y postinstall de las dependencias no se ejecutan hasta que los apruebas |
minimumReleaseAge | No instala versiones publicadas hace menos de 1 día (valor por defecto: 1440 minutos) |
| Workspaces nativos | Monorepos con pnpm-workspace.yaml y filtros por paquete |
pnpm-lock.yaml | Lockfile determinista; versiónalo siempre |
Instalación y versión
| Acción | Comando |
|---|---|
| Instalar en Linux o macOS | |
| Instalar con wget | |
| Instalar en Windows (PowerShell) | |
| Instalar una versión concreta | |
| Ver la versión instalada | |
| Actualizar pnpm (desde v11.10) |
Fija la versión del proyecto en package.json con el campo packageManager. Dentro de ese proyecto, pnpm self-update actualiza solo ese campo. En Docker, copia el binario desde la imagen oficial ghcr.io/pnpm/pnpm (ver la hoja de Docker).
{
"packageManager": "pnpm@12.16.1"
}Dependencias del día a día
| Acción | Comando |
|---|---|
Instalar todo lo del package.json | |
| Añadir una dependencia | |
| Añadir una dependencia de desarrollo | |
| Añadir una versión exacta | |
| Instalar una CLI global | |
| Quitar una dependencia | |
| Instalar solo dependencias de producción | |
Primera vez con globales: preparar PNPM_HOME |
Actualizar e inspeccionar
| Acción | Comando |
|---|---|
| Ver dependencias desactualizadas | |
Actualizar dentro de los rangos de package.json | |
| Elegir qué actualizar, incluidas versiones mayores | |
| Por qué está instalado un paquete | |
| Listar dependencias directas | |
| Buscar vulnerabilidades conocidas | |
| Reducir duplicados en el lockfile | |
| Liberar espacio del store |
Ejecutar scripts y binarios
| Acción | Comando |
|---|---|
Ejecutar un script de package.json | |
| Forma corta (si no choca con un comando de pnpm) | |
| Pasar argumentos al script | |
Ejecutar un binario local de node_modules/.bin | |
| Ejecutar un paquete sin instalarlo | |
| Crear un proyecto desde un starter |
Aprobar scripts de instalación
pnpm no ejecuta los scripts de build de las dependencias hasta que los revisas. Con strictDepBuilds (activo por defecto) la instalación falla si hay builds sin revisar. Tus decisiones se guardan en allowBuilds dentro de pnpm-workspace.yaml; onlyBuiltDependencies e ignoredBuiltDependencies se eliminaron en v11.
| Acción | Comando |
|---|---|
| Revisar los builds pendientes (interactivo) | |
Aprobar unos y denegar otro (con !) | |
| Aprobar los builds de paquetes globales |
# pnpm-workspace.yaml
allowBuilds:
esbuild: true # allowed to run install scripts
core-js: false # reviewed and deniedEvita pnpm approve-builds --all y dangerouslyAllowAllBuilds: true: aprueban todo sin revisar y anulan la protección.
Equivalencias si vienes de otro gestor
| Acción habitual | En pnpm |
|---|---|
| Instalar desde el lockfile en CI | pnpm install --frozen-lockfile |
| Instalar un paquete | pnpm add <paquete> |
| Instalar como dependencia de desarrollo | pnpm add -D <paquete> |
| Desinstalar | pnpm remove <paquete> |
| Instalar globalmente | pnpm add -g <paquete> |
| Ejecutar un paquete puntual sin instalar | pnpm dlx <paquete> |
| Ejecutar un binario del proyecto | pnpm exec <binario> |
| Árbol de dependencias | pnpm list |
Workspaces y monorepos
# pnpm-workspace.yaml (repo root)
packages:
- 'apps/*'
- 'packages/*'| Acción | Comando |
|---|---|
| Ejecutar un script en todos los paquetes | |
| Scripts en paralelo (ej. servidores de desarrollo) | |
| Ejecutar solo en un paquete | |
| Un paquete y todas sus dependencias | |
| Paquetes de una carpeta | |
Solo lo que cambió respecto a main | |
| Añadir una dependencia a un paquete | |
| Enlazar un paquete local del workspace | |
| Añadir una herramienta en la raíz |
Las dependencias internas se declaran con el protocolo workspace:, por ejemplo "@acme/ui": "workspace:*".
Configuración: qué va dónde
| Archivo | Qué contiene |
|---|---|
pnpm-workspace.yaml | Casi toda la configuración: allowBuilds, minimumReleaseAge, nodeLinker, publicHoistPattern, packages |
.npmrc | Solo autenticación, registry, TLS, proxy y local-address |
package.json | packageManager, scripts y dependencias |
Config global (pnpm config set -g) | Ajustes de la máquina como storeDir |
# .npmrc: auth only, never commit real tokens
@acme:registry=https://registry.example.com/
//registry.example.com/:_authToken=${NODE_AUTH_TOKEN}Las variables ${...} se expanden en .npmrc, pero no en las URL de registry dentro de pnpm-workspace.yaml. Guarda el token en el gestor de secretos del CI, nunca en el repositorio.
Integración continua
En CI usa siempre pnpm install --frozen-lockfile: falla si pnpm-lock.yaml no coincide con package.json.
# .gitlab-ci.yml
test:
image: ghcr.io/pnpm/pnpm:12
cache:
key:
files: [pnpm-lock.yaml]
paths: [.pnpm-store]
before_script:
- pnpm config set store-dir .pnpm-store
- pnpm runtime set node 24 -g
- pnpm install --frozen-lockfile
script:
- pnpm testEn GitHub Actions, la documentación oficial usa la acción pnpm/setup (v3) con runtime: node@24 y cache: true; fija la acción a un SHA de commit.