Tag: pnpm

  • pnpm 12 en Rust: los 6 breaking changes que sí te afectan

    pnpm 12 en Rust: los 6 breaking changes que sí te afectan

    Antes de que llegue pnpm 12, un ejemplo de por qué lo vas a querer: un lockfile que instala perfecto en tu portátil y revienta en el runner de CI.

    La traza no ayuda mucho: git@github.com: Permission denied (publickey). Y en tu package.json solo pone "is-positive": "kevva/is-positive".

    Tu máquina tiene claves SSH. El runner no. pnpm resolvió por SSH porque podía, lo grabó así en el lockfile, y el runner se topó con una URL que no puede abrir.

    pnpm 12 arregla eso. Y la forma en que lo arregla dice bastante de cómo está construida esta versión.

    Qué es pnpm 12: una reescritura en Rust que, a propósito, no te pide migrar nada

    pnpm 12.0 salió estable el 26 de agosto de 2026. Es pnpm reescrito entero en Rust.

    Del anuncio oficial de pnpm 12.0, publicado el 26 de agosto de 2026:

    It is a rewrite of pnpm in Rust, and it is deliberately not a migration: the commands, flags, settings, and lockfile format of pnpm 11 all carry over.

    Lee otra vez la parte de deliberately not a migration, porque en el ecosistema JavaScript esa frase es rara. Aquí una major suele traducirse en un sábado peleándote con el build, un codemod que no cubre tu caso y tres dependencias transitivas que ya no compilan.

    En pnpm 12 no. Mismos comandos, mismos flags, mismos settings y el mismo formato de lockfile que pnpm 11. El cambio está debajo: el lenguaje en el que corre la herramienta, no el contrato que tienes con ella.

    Es el mismo movimiento que ya vimos con TypeScript y su compilador en Go: reescribir el motor en un lenguaje nativo sin tocar la superficie que usa el desarrollador. Cuando la API pública no se mueve, la reescritura deja de ser un riesgo y pasa a ser una actualización.

    Dicho esto, "no es una migración" no significa "no cambia nada". Entre el anuncio de la 12.0 y el documento What's different in pnpm 12 hay seis diferencias respecto a pnpm 11 que conviene revisar antes de meterlo en el pipeline.

    Cómo instalar pnpm 12 hoy

    El tag latest de npm sigue apuntando a pnpm 11. Para pnpm 12 tienes que pedir el tag next-12 de forma explícita:

    # Si ya tienes pnpm instalado
    pnpm self-update next-12
    

    Si vienes de otro gestor, el paquete es el mismo con el tag distinto:

    npm install -g pnpm@next-12
    

    pnpm 12 se distribuye como binario nativo compilado desde Rust, y hay vías de instalación que no pasan por npm. Si tu imagen de CI instala pnpm por script, revisa que apunte al tag correcto y no a latest, o seguirás en 11 sin enterarte.

    Los 6 breaking changes de pnpm 12 que sí te van a afectar

    Estos son los seis, y a quién afectan de verdad:

    # Qué cambia en pnpm 12 Te afecta si… Qué hacer
    1 Las dependencias git resuelven por su URL HTTPS canónica; nunca se graba una URL SSH en el lockfile Tienes deps de GitHub, GitLab o Bitbucket en package.json Re-resolverlas una vez con pnpm update <paquete>
    2 Los settings desconocidos de pnpm-workspace.yaml se reportan en vez de ignorarse Tienes pnpm-workspace.yaml, y sobre todo si pinneas la versión de pnpm Corregir las erratas antes de actualizar
    3 Los ciclos de dependencias se cortan siempre en el mismo punto → lockfiles byte-idénticos Tu monorepo tiene librerías internas que se referencian entre sí Nada: es ganancia neta (2–3× en resolución de peers)
    4 Con packageImportMethod: auto, en Linux se prueba hardlink antes que reflink Tu CI corre en Linux sobre btrfs Nada: instala más rápido. En ext4 no cambia
    5 engineStrict sigue aristas, no subárboles Usas engineStrict y tienes paquetes incompatibles colgando de optionalDependencies Verificar que el install sigue pasando
    6 --resolution-only deja de existir y se rechaza con error Lo usas en scripts de package.json o en workflows de CI Sustituir por pnpm peers check

    1. Las dependencias git son identidades, no transportes

    Este es el que más gente va a notar, y es el problema del CI que abre el post.

    Hasta ahora, la URL con la que declarabas una dependencia de GitHub también decidía cómo se descargaba. En pnpm 12 los specifiers de GitHub, GitLab y Bitbucket resuelven por su URL HTTPS canónica. Estas cuatro formas son ahora exactamente la misma dependencia:

    kevva/is-positive
    github:kevva/is-positive
    git+https://github.com/kevva/is-positive.git
    git+ssh://git@github.com/kevva/is-positive.git
    

    Y lo importante: pnpm nunca graba una URL SSH para esos hosts en el lockfile. Un lockfile generado en tu máquina, con tus claves cargadas, instala en un runner que no tiene ninguna.

    ¿Y los repos privados por SSH? Siguen funcionando, pero la reescritura se configura en Git, no en el specifier:

    git config --global url."git@github.com:".insteadOf https://github.com/
    

    pnpm delega en git, así que la regla se aplica sola a todas sus operaciones.

    Un aviso importante: pnpm no reescribe por su cuenta las entradas que ya están en tu lockfile, porque el lockfile es el registro de lo que hay que instalar. Las URLs SSH heredadas de pnpm 11 siguen ahí hasta que re-resuelvas esas dependencias una vez con pnpm update <paquete>.

    Si en tu equipo existe la regla no escrita de "el lockfile lo regenera quien lo tenga configurado", esto te devuelve horas.

    2. Los settings desconocidos en pnpm-workspace.yaml ya no se ignoran

    Antes, una clave mal escrita se descartaba en silencio y tú te quedabas convencido de que la configuración estaba aplicada. En pnpm 12 se reporta, con sugerencia de corrección. Y si tienes una versión de pnpm pinneada en el proyecto, la instalación falla.

    # pnpm-workspace.yaml
    packages:
      - "packages/*"
    
    # Erratas como esta ya no pasan desapercibidas
    packageImportMetod: hardlink
    

    Prepárate para descubrir que llevas meses con un setting que nunca hizo nada.

    3. Los ciclos se rompen siempre en el mismo sitio

    Los grafos de dependencias cíclicas ahora se canonicalizan. Desde la v12.0.0-rc.5, pnpm corta el ciclo en un punto fijo en lugar de donde se lo encuentre la instalación, y ordena los miembros de cada ciclo por package id.

    La consecuencia práctica es que dos instalaciones del mismo proyecto producen lockfiles byte-idénticos. Se acabaron los diffs fantasma en las pull requests.

    Como efecto secundario, en workspaces con muchos ciclos la resolución de peers va 2–3 veces más rápida, consume alrededor de un 25% menos de memoria y el lockfile se encoge bastante al desaparecer variantes duplicadas de peers.

    Si mantienes un monorepo con varias librerías internas que se referencian entre sí —el escenario típico de un workspace Angular como los que montamos en el curso de Angular Moderno—, este es el cambio que más vas a notar en el reloj.

    Con packageImportMethod: auto, pnpm clonaba primero. Ahora en Linux prueba el hardlink antes que el reflink. En macOS se mantiene el clone-first.

    En btrfs esto reduce aproximadamente a la mitad el tiempo que una instalación pasa materializando node_modules desde un store caliente. En ext4 no cambia nada: ahí el clonado nunca estuvo soportado y auto ya hacía hardlink.

    5. engineStrict sigue aristas, no subárboles

    Con engineStrict activado, la instalación falla si un paquete incompatible se alcanza por una arista de dependencies normal de un paquete que sí se está instalando, aunque todo ese subárbol cuelgue de una entrada de optionalDependencies. Lo que no cambia: un paquete al que solo se llega por aristas opcionales —o a través de otro que ya se saltó— se sigue saltando igual que en pnpm 11.

    Traducción: proyectos que instalaban en pnpm 11 porque el paquete problemático quedaba escondido bajo una opcional, ahora fallan. Es más correcto, pero puede sorprenderte en el primer install después de actualizar.

    6. --resolution-only ya no existe

    pnpm 12 rechaza el flag con un error. El sustituto es un comando propio:

    # pnpm 11
    pnpm install --resolution-only
    
    # pnpm 12
    pnpm peers check
    

    Busca --resolution-only en los scripts de tu package.json y en los workflows de CI antes de actualizar. Es un grep de diez segundos que te ahorra un pipeline en rojo.

    Las novedades de pnpm 12 que de verdad usarás

    La estrella no es una cifra de rendimiento, es un cambio de rol: pnpm ahora provisiona otros gestores de paquetes. npm, Yarn Classic, Yarn Berry, Yarn 6 (yarnpkg/zpm) y Bun.

    pnx yarn@4 install
    pnx npm@11 ci
    pnx node@22
    

    pnx ejecuta uno de ellos para un solo comando. Y si lo quieres permanente:

    pnpm shim add yarn
    

    Eso enlaza un yarn que ejecuta lo que pinnee el proyecto en el que estés. En la misma línea, los global bins son conscientes del proyecto: un Node.js, un Deno o un Bun instalados globalmente pueden seguir la versión que fija el proyecto actual, controlado por el setting globalShims.

    Si mantienes varios repos con runtimes distintos, esto se come de un bocado buena parte de la razón por la que tienes nvm. Y si estás valorando mover backend a Bun, ya conté dónde Bun reemplaza a Node.js de verdad y dónde no.

    El resto del cambiario, en corto:

    • Registry revisions. Artefactos de reemplazo identificados por SHA-512 y anotados como revision: N en el lockfile. Sirve para servir artefactos parcheados sin bump de versión.
    • pnpm init pinnea la última release de pnpm, no la que estás corriendo.
    • Aprobación por lotes en staged publishing con pnpm stage approve.
    • audit.ignorePrune. Con el setting activo, pnpm audit --fix borra de tu lista de ignorados las GHSA que ya no aparecen en el informe, para que no se te acumulen advisories de dependencias que ya ni existen.
    • Los comandos globales se niegan a correr bajo sudo y devuelven ERR_PNPM_SUDO_NOT_SUPPORTED.
    • hooks.filterLog queda deprecado. Si lo usas en tu .pnpmfile.cjs, tienes trabajo pendiente.
    • Caché remota de side-effects: proof of concept, opt-in. No la metas en producción todavía.

    Y un fix pequeño con impacto grande si trabajas en contenedores: cuando ningún directorio por encima del proyecto acepta hardlinks, el store se crea dentro del propio proyecto, en node_modules/.pnpm-store.

    Eso arregla los entornos sandbox y containerizados que hasta ahora fallaban sin explicación clara —justo el tipo de fricción que intentas eliminar cuando montas entornos de desarrollo reproducibles con dev containers.

    Checklist para actualizar a pnpm 12 sin sustos

    Media hora, en este orden:

    1. Busca --resolution-only en scripts y workflows. Sustitúyelo por pnpm peers check.
    2. Actualiza en una rama: pnpm self-update next-12 y después un pnpm install en limpio.
    3. Lee los avisos de pnpm-workspace.yaml. Si aparecen settings desconocidos, corrígelos ahora que solo avisan.
    4. Re-resuelve las dependencias git una vez: pnpm update <paquete> por cada dependencia de GitHub, GitLab o Bitbucket. pnpm no reescribe esas entradas por su cuenta —el lockfile es el registro de lo que hay que instalar—, así que un install normal te deja las URLs SSH heredadas de pnpm 11 donde estaban. Revisa el diff: ahí sí deben desaparecer.
    5. Si usas engineStrict, comprueba que el install sigue pasando; el criterio por aristas es más estricto que antes.
    6. Corre la suite completa en CI con el lockfile nuevo antes de mergear. Un lockfile byte-idéntico solo vale de algo si tus tests confirman que el árbol resultante es el que esperabas, y esa disciplina de pipeline es la misma que trabajamos en el curso de Testing en Angular con Jest y Testing Library.

    Si los seis pasos pasan, ya estás en pnpm 12.

    ¿Merece la pena actualizar a pnpm 12 ya?

    La noticia no es que pnpm sea ahora más rápido. La noticia es que un equipo ha reescrito una herramienta entera en otro lenguaje y ha decidido que el coste de esa decisión lo pagan ellos, no tú.

    Eso es una postura de diseño, y merece copiarse. La próxima vez que reescribas un módulo interno, pregúntate cuánto de tu refactor es mejora real y cuánto es trabajo que le estás pasando a quien lo consume.

    Actualiza en una rama esta semana. Si tienes dependencias git en el package.json, el cambio del punto 1 te paga la actualización él solo.

    Yo voy a pasarlo esta semana por los repos de Labs, con el checklist de arriba y sin tocar el lockfile de pnpm 11 más de lo imprescindible. Contaré qué se rompió —si es que se rompe algo— en Dominicode Labs, que es donde vamos pasando estas herramientas por proyectos reales antes de decidir qué entra en el stack y qué se queda fuera.


    Preguntas frecuentes sobre pnpm 12

    ¿Puedo instalar pnpm 12 con pnpm self-update a secas?

    No. El tag latest de npm sigue apuntando a pnpm 11, así que un self-update normal te deja donde estabas. Tienes que pedir el tag de forma explícita con pnpm self-update next-12, o instalar pnpm@next-12 desde npm si vienes de otro gestor.

    ¿Tengo que regenerar el lockfile al pasar a pnpm 12?

    El formato de lockfile de pnpm 11 se mantiene, así que el tuyo sigue siendo válido. Ahora bien, si tienes dependencias git de GitHub, GitLab o Bitbucket, te interesa re-resolverlas una vez con pnpm update <paquete>: pnpm no reescribe solo las entradas ya escritas, así que las URLs SSH heredadas de pnpm 11 siguen ahí hasta que se lo pidas. Cuando desaparecen, el lockfile pasa a ser instalable en cualquier runner de CI. También lo notarás en workspaces con muchos ciclos, donde el lockfile se encoge al eliminarse variantes duplicadas de peers.

    ¿Qué hago si mi CI usa --resolution-only?

    Sustitúyelo por pnpm peers check. El flag --resolution-only ya no existe en pnpm 12 y la ejecución termina con error, así que el pipeline se te va a rojo en el primer build si no lo cambias antes de actualizar.

    ¿Cuánto se gana de rendimiento con pnpm 12?

    Depende del proyecto, y solo hay cifras oficiales para dos escenarios concretos. En workspaces con muchos ciclos, la resolución de peers va entre 2 y 3 veces más rápida y consume alrededor de un 25% menos de memoria. En Linux sobre btrfs, priorizar hardlink frente a reflink reduce aproximadamente a la mitad el tiempo de materializar node_modules; en ext4 no cambia. Cualquier otra cifra espectacular que veas circulando por blogs de terceros no está en el anuncio oficial, así que trátala como no verificada hasta que la midas en tu propio repositorio.

    ¿Qué cambia en pnx con pnpm 12?

    pnx no es un comando nuevo: es el alias de pnpm dlx —descarga un paquete del registro, lo ejecuta y no lo deja instalado— y ya existía antes de la 12. Lo que cambia en pnpm 12 es a qué apunta cuando nombras un gestor de paquetes o un runtime. Desde la v12.0.0-rc.6, pnx yarn@4 install, pnx npm@11 ci o pnx node@22 te dan la herramienta de verdad y no el paquete npm que comparte su nombre: en npm, yarn se queda en Classic, Yarn 4 se publica como @yarnpkg/cli-dist y Yarn 6 no está. Si la quieres permanente, pnpm shim add yarn enlaza un yarn que respeta la versión que pinnee cada proyecto.

    ¿Es seguro meter pnpm 12 en producción ya?

    La 12.0 es una release estable y mantiene comandos, flags, settings y formato de lockfile de pnpm 11, así que la superficie de riesgo es baja. Repasa los seis breaking changes en una rama antes de mergear y deja fuera la caché remota de side-effects, que es un proof of concept opt-in y no está pensada todavía para pipelines críticos.

    ¿Por qué mi lockfile de pnpm falla en CI con Permission denied (publickey)?

    Porque el lockfile grabó una URL SSH para una dependencia de git y el runner de CI no tiene claves SSH cargadas. Ocurre cuando quien generó el lockfile sí las tenía: pnpm 11 resolvía por SSH porque podía y lo dejaba escrito. pnpm 12 lo corta de raíz al resolver los specifiers de GitHub, GitLab y Bitbucket por su URL HTTPS canónica, de modo que nunca graba una URL SSH para esos hosts. Para arreglar un lockfile ya existente no basta con actualizar: re-resuelve esas dependencias una vez con pnpm update <paquete>, porque pnpm no reescribe por su cuenta las entradas que ya están escritas.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.