Inicio / Artículos / npm vs pnpm: Comparación de almacenamiento, velocidad y compromisos en el mundo real

npm vs pnpm: Comparación de almacenamiento, velocidad y compromisos en el mundo real

Este artículo compara cómo npm y pnpm gestionan el almacenamiento de dependencias, la velocidad de instalación y los flujos de trabajo en monorepo para ayudarlo a elegir la herramienta adecuada para su proyecto.

2380 palabras

Si has dedicado tiempo a desarrollar aplicaciones con React, Next.js, Node.js o cualquier otro entorno basado en JavaScript moderno, es muy probable que hayas escrito esta orden más veces de las que puedes contar:

npm install

Simplemente funciona. Todos lo reconocen. Casi todos los tutoriales en línea lo utilizan.

Luego, eventualmente, alguien te dice algo como:

"¿Por qué sigues usando npm? Simplemente usa pnpm."

Así que pruebas pnpm.

Y en poco tiempo comienzas a preguntarte:

¿Es pnpm realmente una mejora, o es solo otra de esas discusiones sobre herramientas para JavaScript que desaparecen en unos meses?

Esa es una pregunta legítima.

Npm no está roto en absoluto. Es familiar, fiable y viene incluido automáticamente con Node.js. Abandonarlo requiere una justificación real.

Cuando analizas cómo funciona realmente cada herramienta, te das cuenta de que la verdadera cuestión no es simplemente npm versus pnpm.

Se trata de cómo gestionan las dependencias, cuánto espacio en disco consumen, cómo se comportan las instalaciones bajo diferentes condiciones y qué tipo de proyecto estás creando.

Y la pregunta más importante:

¿Cuál de los dos tiene sentido que uses realmente?

npm y pnpm resuelven el mismo problema fundamental

Comencemos con algo obvio.

Tanto npm como pnpm son gestores de paquetes creados para el mundo de Node.js.

Ambos obtienen paquetes del registro de npm y se basan en las mismas convenciones de package.json.

Supongamos que tu proyecto necesita React. Puedes instalarlo usando npm:

npm install react

O bien puedes optar por pnpm en su lugar:

pnpm add react

De cualquier manera, al final tendrás React instalado.

No has pasado a un ecosistema de JavaScript completamente diferente.

Lo que realmente cambia es lo que ocurre internamente una vez que los paquetes se instalan y almacenan en tu máquina.

Esa es la parte donde el diseño de pnpm comienza a destacarse.

Dónde realmente difieren: cómo se almacenan las dependencias

Imagina que tienes cinco proyectos de JavaScript separados en tu ordenador.

Cada uno de ellos depende de React.

Con la configuración clásica de npm, cada proyecto mantiene su propia carpeta node_modules independiente que contiene los paquetes que necesita.

Si esto ocurre en muchos proyectos, terminas con muchos archivos duplicados que ocupan espacio.

pnpm sigue un enfoque diferente.

Almacena los paquetes en un único almacenamiento con direcciones de contenido y luego crea enlaces desde ese almacenamiento hacia cada proyecto que los necesita.

En pocas palabras, en lugar de duplicar el mismo paquete una y otra vez para cada proyecto, pnpm puede reutilizar una copia que ya se encuentra en su almacén central.

Imagínenselo de esta manera:

Project A ──┐
Project B ──┤
Project C ──┼── Shared package store
Project D ──┤
Project E ──┘

El mecanismo real detrás de esto es más complejo de lo que sugiere ese diagrama sencillo, pero el concepto subyacente es lo que realmente importa aquí.

pnpm está diseñado para minimizar las copias redundantes.

Y si manejas varios proyectos al mismo tiempo, esa elección de diseño puede reducir significativamente el uso del disco.

¿Realmente pnpm instala las cosas más rápido?

Esto suele ser lo primero que quieren saber los desarrolladores.

La respuesta honesta:

Frecuentemente, sí — pero no siempre.

Muchos estudios de rendimiento indican que pnpm supera con creces a npm en velocidad.

El problema es que la velocidad de instalación depende de una gran cantidad de variables.

Tu conexión a Internet también es importante.

Igualmente lo es el hardware de tu disco.

También importa la cantidad de paquetes de los que depende tu proyecto.

Si esos paquetes ya están en caché localmente marca una diferencia.

También influye el tamaño del proyecto.

Incluso ejecutar una instalación nueva frente a reinstalar algo que ya se ha descargado anteriormente puede producir resultados muy diferentes.

La arquitectura de pnpm está diseñada para descargas y enlaces eficientes, y como mantiene un almacén compartido, los paquetes que ya tienes localmente pueden reutilizarse directamente en lugar de volver a descargarse.

Ese es el escenario en el que sus ventajas realmente se hacen notar.

Las instalaciones “frías” frente a las “calientes” marcan una gran diferencia

Este es un detalle que a menudo se pasa por alto cuando la gente compara gestores de paquetes.

Imagina que estás instalando un paquete por primera vez.

No le queda más remedio que descargarlo desde cero.

Eso es, en esencia, un escenario de inicio desde cero.

Ahora imagine que ese mismo paquete ya existe en otro proyecto de su máquina.

Eso representa un punto de partida completamente diferente.

Es precisamente aquí donde el almacén compartido de pnpm demuestra su utilidad.

En lugar de tratar cada proyecto como un sistema completamente aislado, pnpm puede recuperar los paquetes que ya tiene almacenados localmente.

Así que si crea proyectos nuevos con frecuencia, borra las carpetas node_modules, reinstala dependencias con frecuencia o pasa de un repositorio a otro, la eficiencia de pnpm se vuelve mucho más evidente con el tiempo.

Pero si su flujo de trabajo consiste solo en un proyecto sencillo donde instala las dependencias una sola vez, probablemente no notará mucha diferencia.

Por eso evitaría afirmar:

"pnpm es siempre la opción más rápida."

Una formulación más precisa sería:

pnpm tiende a ser considerablemente más eficiente, especialmente en flujos de trabajo basados en instalaciones repetidas o árboles de dependencias complejos.

npm ha evolucionado mucho más allá de su antigua reputación

Hay otro punto que vale la pena mencionar aquí.

Muchas conversaciones sobre npm frente a pnpm presentan a npm como una herramienta obsoleta de la que los desarrolladores deberían haber pasado hace tiempo.

Esa descripción no es del todo precisa.

npm ha avanzado mucho.

La versión actual soporta características como espacios de trabajo, archivos lockfile y npm ci para lograr instalaciones reproducibles dentro de pipelines CI.

Como ejemplo:

npm ci

se utiliza con frecuencia cuando se desea una instalación limpia basada en archivos lockfile.

Llamar lento, obsoleto o mal diseñado a npm no es justo.

Sigue siendo una opción completamente sólida para una gran parte de los proyectos existentes.

Lo que diferencia a pnpm es que adoptó decisiones de diseño orientadas específicamente a la eficiencia, y esas decisiones se vuelven cada vez más evidentes a medida que tu proyecto crece.

Otra distinción con la que se encuentran los desarrolladores: el aislamiento de dependencias

Esto no es obvio de inmediato, especialmente si eres nuevo en este ecosistema.

Imagina esta situación: tu aplicación depende del paquete A. El paquete A, a su vez, depende del paquete B. Tú nunca instalaste B personalmente; ni siquiera lo incluiste en tu propio manifiesto. Sin embargo, debido a la forma en que se estructuran los archivos node_modules, tu código podría seguir siendo capaz de require o import a B directamente, y funcionará.

Por un tiempo, no parece haber ningún problema.

Luego, el paquete A se actualiza y reemplaza sus dependencias. B ya no está en la ubicación que tu código esperaba, y de repente tu aplicación lanza un error inesperado.

Esta situación tiene un nombre: una dependencia fantasma. Estás confiando en algo que en realidad nunca debió ser tu punto de apoyo.

pnpm evita esto por diseño. Su estructura predeterminada es mucho más estricta respecto a lo que un paquete puede ver realmente, lo que hace mucho más difícil que tu proyecto dependa de algo que nunca declaró explícitamente como dependencia.

Esa es una garantía verdaderamente valiosa. Te obliga a ser honesto sobre las necesidades reales de tu aplicación, en lugar de beneficiarte de una casualidad en la organización de los archivos. Ese tipo de corrección suele ser más importante a largo plazo que ahorrar unos segundos en la instalación.

El escenario donde pnpm brilla realmente: monorepos

Probablemente este sea el caso más convincente para optar por pnpm.

Imagínese un código de una empresa estructurado de la siguiente manera:

my-project/
│
├── apps/
│   ├── web/
│   └── admin/
│
├── packages/
│   ├── ui/
│   ├── utils/
│   └── config/
│
└── package.json

Existen varias aplicaciones y un puñado de paquetes internos compartidos, todos ubicados en un mismo repositorio. Esa configuración es lo que la gente denomina monorepo.

Npm sí admite espacios de trabajo, por lo que crear un monorepo con npm es totalmente posible. Pero pnpm ha invertido mucho más esfuerzo específicamente en herramientas para monorepos. Ofrece cosas como su protocolo de espacios de trabajo, flags de filtrado para ejecutar comandos en paquetes específicos, y un modelo de dependencias diseñado teniendo en cuenta repositorios con múltiples paquetes; todo esto puede hacer que un códigobase grande sea notablemente más fácil de manejar.

Si está manteniendo un pequeño proyecto personal, todo esto en realidad no le importa.

Pero si estás manteniendo un repositorio con múltiples aplicaciones y docenas de paquetes compartidos internos, estas herramientas se vuelven mucho más relevantes.

Pasar de npm a pnpm es un cambio sencillo

Una razón común por la que los desarrolladores evitan probar pnpm es la suposición de que tendrán que aprender un conjunto completo de comandos nuevo.

Eso no es realmente cierto. La mayoría de los comandos cotidianos se corresponden casi uno a uno.

Instalar dependencias con npm se ve así:

npm install

Con pnpm, es:

pnpm install

Agregar un paquete en npm:

npm install axios

se convierte en esto en pnpm:

pnpm add axios

Agregar una dependencia de desarrollo en npm:

npm install -D typescript

se convierte en:

pnpm add -D typescript

Desinstalar un paquete en npm:

npm uninstall axios

se convierte en:

pnpm remove axios

Ejecutar un script en npm:

npm run dev

puede acortarse a:

pnpm dev

Y si ya te sientes cómodo con npx, pnpm tiene su propio equivalente:

pnpm dlx

Por lo tanto, la curva de aprendizaje aquí es mínima.

Casos en los que npm sigue siendo la mejor opción

Si estás introduciendo a alguien en JavaScript o Node.js por primera vez, npm es la elección natural para comenzar. No porque sea técnicamente superior en todos los aspectos, sino porque viene preinstalado por defecto, y los principiantes ya tienen mucho que asimilar sin tener que tomar una decisión adicional sobre un gestor de paquetes.

Si un tutorial te indica que ejecutes:

npm install express

deberías poder escribirlo directamente y seguir aprendiendo el concepto que se está explicando.

Npm también es la opción adecuada cuando te sumerges en un código base que ya está construido alrededor de él. No tiene mucho sentido insistir en usar otro gestor de paquetes en ese contexto.

“El equipo siempre ha utilizado npm, pero aquí se prefiere pnpm, así que convirtamos toda la configuración.”

En un entorno de equipo, es mejor mantener la consistencia con lo que utilizan los demás que optimizar según las preferencias individuales.

Casos en los que pnpm comienza a tener más sentido

PNPM se vuelve más atractivo a medida que un proyecto o flujo de trabajo crece en escala.

Si manejas regularmente varios proyectos en JavaScript al mismo tiempo, el almacenamiento dirigido por contenido compartido de pnpm puede reducir el uso redundante del disco en ellos. Si tu árbol de dependencias es grande y complejo, las instalaciones más rápidas y eficientes comienzan a ser más importantes. Y si estás gestionando un monorepo, las funciones de espacio de trabajo de pnpm merecen una consideración seria.

El aislamiento de dependencias es otra razón para optar por él: si los límites estrictos entre lo que se declara y lo que se puede utilizar son realmente importantes para tu proyecto, pnpm los aplica por defecto.

En pocas palabras: cuanto más grande y desordenada se vuelve la configuración de JavaScript, más atractivo resulta pnpm.

Entonces, ¿cuál gana en velocidad?

Si se busca una respuesta única, pnpm suele tener ventaja en la eficiencia de instalación, especialmente cuando su almacén compartido ya tiene los paquetes almacenados localmente.

Dicho esto, no sería preciso afirmar algo como:

"pnpm es exactamente dos veces más rápido que npm."

Ese tipo de afirmación simplifica demasiado las cosas. Los resultados de las pruebas de rendimiento varían mucho según las condiciones. Ejecutar una instalación completamente nueva a través de una conexión de red rápida no es comparable con reinstalar paquetes en una máquina que ya tiene la mayoría de ellos almacenados localmente. Además, un entorno CI también se comporta de manera diferente a una máquina local.

Por lo tanto, si el gráfico de pruebas de rendimiento es la única razón para considerar cambiar de gestor de paquetes, lo mejor es examinar su propio flujo de trabajo antes de tomar esa decisión.

Qué elegiría yo

Para un proyecto pequeño en React, npm cumple con la tarea sin problemas.

Igual ocurre con un proyecto de aprendizaje: npm es suficiente.

Si se une a un repositorio de código ya existente, utilice lo que el equipo haya estandarizado previamente.

No obstante, para un monorepo grande, pnpm se convierte en una opción muy competitiva.

Y si trabajas en una máquina donde constantemente pasas de un proyecto a otro en JavaScript, pnpm suele ser la opción más práctica.

Todo esto explica por qué no existe un ganador universal en este caso.

No cambies solo porque pnpm está de moda

Este podría ser el punto más importante de toda esta comparación.

No necesitas migrar cada proyecto existente de npm a pnpm solo porque aparece constantemente en las discusiones de desarrolladores en línea.

Tampoco necesitas cambiarlo solo porque alguien insiste:

"npm está muerto."

No es así. Ambas herramientas están siendo mantenidas activamente, ambas cuentan con ecosistemas maduros y ambas son perfectamente capaces de manejar proyectos modernos en JavaScript.

La verdadera pregunta no es “¿cuál gestor de paquetes es objetivamente el mejor?”. Es “¿qué gestor de paquetes se adapta a mi forma de trabajar?”

Si estás creando aplicaciones pequeñas, aprendiendo el lenguaje o trabajando en un equipo que ya utiliza npm, seguir con npm es una opción completamente razonable.

Pero si manejas proyectos grandes, múltiples repositorios o monorepos y deseas un almacenamiento de dependencias más eficiente además de instalaciones más rápidas, entonces vale la pena probar pnpm.

Reflexiones finales

Al iniciar esta comparación entre npm y pnpm, parecía que habría un veredicto claro y sencillo: npm como la opción obsoleta y pnpm como la mejora rápida.

La realidad resultó ser más matizada que eso.

La principal ventaja de npm es su simplicidad y el hecho de que casi todos ya lo conocen. Es la opción por defecto por una buena razón.

Las principales fortalezas de pnpm son su modelo de almacenamiento de dependencias, su eficiencia durante las instalaciones y las herramientas que ofrece para proyectos a gran escala.

Así que si eres nuevo en JavaScript, no te angusties por la decisión: simplemente usa npm y comienza a desarrollar.

Si ya dominas Node.js y tus proyectos están creciendo, prueba pnpm para ver si mejora tu flujo de trabajo diario.

En última instancia, el gestor de paquetes que elijas no es lo que hace que una aplicación sea buena.

Tu código sí lo hace.

Lecturas relacionadas

  • Node.js Streams más allá de lo básico: Memoria, backpressure y fallos reales — Aprenda cómo los streams de Node.js interactúan con Web Streams, los ahorros de memoria medidos mediante pruebas reales, y los errores en producción que solo aparecen bajo carga.