Inicio / Artículos

Cambiar un proyecto Node de npm a pnpm sin afectar al equipo

npm vs pnpm en cuanto a la estructura del disco, dependencias fantasma y archivos de bloqueo; luego, una migración del equipo de Node.js utilizando pnpm import, la opción only-allow y un campo packageManager fijado.

Editor: REACTAPP.TOP6 min de lectura1317 palabras

Fuentes: Switching from npm to pnpm

Los gestores de paquetes deciden cómo se almacenan las dependencias en el disco, qué archivo de bloqueo se compromete y cuán estrictas son las importaciones cuando surge un problema. Para muchos proyectos de Node, el valor predeterminado sigue siendo npm. Los equipos que mantienen varios repositorios también se enfrentan a un flujo constante de advertencias de seguridad que solicitan actualizaciones de versión. Dependabot puede realizar algunas de esas actualizaciones automáticamente; otras requieren intervención manual porque las soluciones transitivas chocan entre sí, o porque la respuesta definitiva es reemplazar el paquete por completo.

More o menos en ese mismo período, GitHub ajustó Dependabot de modo que las solicitudes de versión no relacionadas con la seguridad esperen tres días antes de abrirse. Ese cambio en la política es en su mayor parte independiente de la elección del gestor de paquetes, pero indica cuán problemáticas se habían vuelto las actualizaciones automáticas.

Mientras tanto, los incidentes en la cadena de suministro siguen apareciendo en las noticias. Los paquetes comprometidos o vulnerables se encuentran dentro de aplicaciones que incorporan conjuntos de íconos, herramientas de autenticación y utilidades de tokens, por lo que el radio de afectación crece con cada enlace transitivo. Las alertas de seguridad rara vez llegan una por una; una computadora portátil que utilice varios servicios recibirá advertencias relacionadas con analizadores transitivos, kits de interfaz de usuario y middleware de autenticación en la misma semana. Los bots automáticos son útiles cuando el problema es mecánico, pero tienen dificultades cuando una versión importante reescribe las API o cuando dos dependencias no concuerdan respecto a un recurso compartido. En esas situaciones, es razonable preguntarse si el propio instalador puede reducir el riesgo: rechazando dependencias ficticias, compartiendo el contenido en el disco para que las auditorías vean una sola copia de la versión, y ralentizando las publicaciones completamente nuevas hasta que el ecosistema haya tenido tiempo de analizarlo.

Una sugerencia recurrente es pasar de npm a pnpm: comandos similares en el uso diario, un modelo de instalación más estricto y, por lo general, menos carga en el disco. Las secciones siguientes comparan ambos sin afirmar un ganador universal, solo con suficiente detalle como para decidir si el cambio merece el costo de la migración.

Información general sobre npm / pnpm

Un breve resumen de cada herramienta:

npm

  • Viene incluido como gestor de paquetes predeterminado con Node.js.
  • Se encarga de la instalación de dependencias y de los scripts del package.json.
  • Los comandos más utilizados incluyen npm install (instalar desde el archivo de lock/manifest), npm install <nombre> (agregar una dependencia), npm run <script> y npm uninstall <nombre>.
  • Escribe el archivo package-lock.json.
  • Almacena los paquetes en la carpeta node_modules.

npm también incluye npx, que ejecuta un paquete sin añadirlo al proyecto ni instalarlo de forma global. Las herramientas de scaffolding como npx create-vite@latest project-name lo descargan temporalmente, lo ejecutan y dejan package.json sin cambios. La distinción con npm install es intencionada: ejecución única frente a una dependencia permanente.

pnpm

  • Un gestor de paquetes de terceros con la misma función —dependencias y scripts— implementada de manera diferente en el disco.
  • Los comandos son similares: pnpm install, pnpm add <name>, pnpm run <script>, pnpm remove <name>.
  • Suele ocupar menos espacio en disco y finaliza las instalaciones más rápido al almacenar cada versión una sola vez.
  • Restringe las importaciones a lo que declara package.json.
  • Utiliza pnpm-lock.yaml en lugar de package-lock.json.
  • Aplica valores predeterminados más estrictos para las versiones recién publicadas (por ejemplo, retrasando su adopción).
  • El ejecutor de uso único similar a npx es pnpm dlx; resulta útil al crear estructuras con create-vite en la última versión, por ejemplo. Muchos generadores también aceptan pnpm create. Para archivos binarios ya presentes en node_modules, pnpm exec es el ejecutor local.

    Ventajas y desventajas de pnpm

    Los compromisos son tan importantes como los eslóganes:

    • npm copia los paquetes a node_modules de cada proyecto, lo que duplica el contenido entre repositorios; pnpm mantiene una única copia con dirección de contenido por versión y establece enlaces desde los proyectos.
    • Esa estructura suele reducir el uso de disco y acelerar las instalaciones repetidas.
    • La resolución históricamente más simple de npm puede permitir que el código requiera un paquete que nunca fue declarado; pnpm rechaza las importaciones no declaradas, lo que reduce la superficie de ataque accidental.
    • La adopción tardía por parte de pnpm de las versiones completamente nuevas disminuye la posibilidad de descargar inmediatamente una versión comprometida.
    • Npm ha ido adquiriendo capacidades relacionadas con el tiempo, pero varias siguen siendo opcionales en lugar de predeterminadas.
    • Pnpm necesita un paso de instalación separado; npm viene incluido con Node.
    • Los plugins antiguos que asumen la estructura de npm pueden requerir ajustes debido a los enlaces más estrictos de pnpm.
    • La memoria muscular del equipo sigue inclinándose hacia npm, por lo que la adaptación puede requerir un breve período de ajuste.

    Las diferencias en la estructura de los discos se manifiestan rápidamente en los ejecutores CI que almacenan de forma deficiente node_modules y en las máquinas de los desarrolladores que tienen descargadas una docena de aplicaciones. El almacenamiento con direcciones de contenido significa que los segundos y terceros proyectos que necesitan lodash@4.x crean principalmente enlaces en lugar de otro árbol completo. Una visibilidad más estricta de las dependencias también modifica el proceso de depuración: cuando una importación falla porque el paquete nunca fue declarado, el error se produce de forma evidente durante la instalación o la verificación de tipos, en lugar de ser un error inesperado en tiempo de ejecución causado por que otro paquete lo incluyó por casualidad.

    Cambiar a pnpm

    Una instalación global mínima se ve así:

    // Installation command (once)
    npm install -g pnpm
    
    // Usage
    pnpm install
    pnpm add [package name]
    pnpm run [script name]
    pnpm remove [package name]
    

    Después de la primera instalación exitosa en un proyecto, esperar encontrar pnpm-lock.yaml junto a (y eventualmente en lugar de) package-lock.json.

    Existen otros métodos de instalación, incluidos scripts independientes; la documentación de instalación de pnpm los enumera.

    Migrar un proyecto npm existente generalmente implica eliminar node_modules y package-lock.json, y luego ejecutar pnpm install. La mayoría de las aplicaciones funcionan sin problemas; sin embargo, los complementos nativos complejos o los resolvers antiguos pueden requerir soluciones puntuales.

    Para establecer versiones a partir de un archivo lockfile existente, ejecute pnpm import. Para eliminar los restos de npm:

    // For macOS/Linux/Git Bash:
    rm -rf node_modules package-lock.json
    
    // For Windows PowerShell:
    rm -Recurse -Force node_modules, package-lock.json
    

    Para evitar ejecuciones accidentales de npm install posteriormente, agregue una protección preinstall:

    "scripts": {
      "preinstall": "npx only-allow pnpm"
    }
    

    Luego, añada la herramienta como dependencia de desarrollo:

    pnpm add -D only-allow
    

    Para fijar la CLI exacta para los colaboradores, utilice el campo packageManager (cambie la cadena de versión según sea necesario):

    {
      "packageManager": "pnpm@11.22.0"
    }
    

    Ese pin mantiene a CI y las computadoras portátiles en una misma versión de CLI; recuerde actualizarlo intencionalmente cuando el equipo realice actualizaciones.

    Inspeccione y actualícese automáticamente con:

    pnpm --version
    
    pnpm self-update
    

    Si la actualización automática funciona mal, reinstálelo globalmente con npm install -g pnpm y reinicie la shell.

    Después de un cambio exitoso, debería ver:

    • package-lock.json desaparecido.
    • pnpm-lock.yaml presente.
    • package.json sin cambios, aparte de los pins o scripts que haya agregado.
    • node_modules reescrito bajo el enlazador de pnpm (o recreado con un pnpm install nuevo).
    • Comandos cotidianos que difieren principalmente por el nombre del herramienta al inicio.
    • Ejecutores únicos mediante pnpm dlx donde anteriormente se utilizaba npx.

    La documentación oficial sigue siendo el recurso adecuado para abordar casos límite; las notas anteriores son suficientes para evaluar la migración y realizar un cambio de sistema rutinario.

    Considere el primer repositorio migrado como un ensayo: ejecute el conjunto de pruebas, confirme que las compilaciones con Docker sigan funcionando y verifique que los complementos nativos se compilen correctamente con el nuevo enlazador. Una vez que este proceso sea sencillo, aplicar el mismo parámetro packageManager y la regla de protección only-allow en los servicios relacionados mantiene la consistencia de toda la infraestructura. Si una herramienta antigua realmente no puede adaptarse al formato de pnpm, aíslela en lugar de abandonar los valores predeterminados más estrictos en todos los demás casos.

    Lecturas relacionadas

  • Master Playwright GitHub Actions YAML para ejecuciones de pruebas CI — Lee un flujo de trabajo de Playwright GitHub Actions de principio a fin: sobre desencadenantes, tareas, descarga de código, configuración de Node, npm ci, navegadores, pruebas y generación de informes.
  • Driftr: un gestor de versiones de Node basado en shims mantenido tras el estancamiento de Volta — Reemplaza los silenciosos flujos de trabajo de Volta con shims en Go, fijación de versiones del proyecto y optimización del almacén compartido de pnpm que evita la duplicación de node_modules en cada repositorio.