¡Hola a todos!
Estoy seguro de que has visto proyectos de Node.js usando diferentes administradores de paquetes, es decir:
Lo he visto yo mismo y he trabajado con todo lo anterior, pero siempre tuve una pregunta en mente: ¿qué impulsa a las personas/equipos a usar hilo o pnpm en lugar de npm ? ¿Cuáles son las ventajas? ¿Hay alguna desventaja?
Bueno… ¡descubrámoslo!
Reglas de comparación de desempeño
Decidí comparar npm , Yarn y pnpm en términos de su "velocidad"...
Verás 3 medidas a continuación:
Genere un archivo de bloqueo sin caché.
Instale dependencias de archivos de bloqueo existentes sin ningún caché.
Instale dependencias de archivos de bloqueo existentes con caché global.
Hay dos tipos de caché:
Global.
Generalmente se almacena en el directorio de inicio del usuario (por ejemplo,
~/.yarn/berry/cache
).
Local.
Almacenado en el directorio del proyecto (fe,
<project-dir>/.yarn
).
Si bien los casos de uso 2 y 3 son los casos de uso más comunes en mi experiencia, también tomé el n.° 1 por si acaso (aunque es un caso muy raro).
Utilicé un proyecto de muestra de create-react-app como ejemplo para los puntos de referencia.
npm
Es un administrador de paquetes predeterminado para el ecosistema Node.js. ¿Qué más decir? Viene con el paquete de instalación, por lo que básicamente está listo para usar cuando instala Node.js en su máquina (o en cualquier proveedor de CI si configura Node.js allí).
En mi opinión, eso es una gran “ventaja”: ¡no es necesario instalarlo por separado!
No hay nada extraordinario allí, simplemente... ¡funciona! Y no he visto ningún error importante a lo largo de los años: parece bastante estable y hace el trabajo.
Las características de npm que usé hasta ahora:
- Administrar dependencias (instalar, eliminar, actualizar)
- Publicar paquetes (privados, públicos)
- Paquetes de enlace local
- Administrar espacios de trabajo.
Administrar dependencias
npm almacena las dependencias en la carpeta node_modules
de la raíz de su proyecto. Muy claro.
ℹ️ package-lock.json
almacena información sobre los registros de los paquetes enumerados; resulta MUY útil si tiene paquetes de un solo ámbito, es decir, @example-company
en diferentes registros (por ejemplo, paquetes npm y GitHub ):
Ahora, veamos cómo se comporta en términos de velocidad de instalación…
Generar package-lock.json sin caché
Tomópackage-lock.json
e instale dependencias sin ningún caché.
Comando utilizado:
npm i
Instale dependencias desde package-lock.json sin ningún caché
Tomópackage-lock.json
sin ningún caché.
Comando utilizado:
npm ci
Instalar dependencias desde package-lock.json con caché global
Tomópackage-lock.json
con caché global.
Comando utilizado:
npm ci
Administrar espacios de trabajo
Pude crear un espacio de trabajo y administrar dependencias para todo el espacio de trabajo a la vez y para proyectos específicos por separado.
En otras palabras, hace el trabajo sin errores ni problemas, y la documentación oficial es bastante sencilla.
Funciones del espacio de trabajo que utilicé hasta ahora:
- Instale dependencias para todos los proyectos dentro del espacio de trabajo.
- Instalar dependencias para un único proyecto específico.
- Ejecute un único script para todos los proyectos a la vez de forma recursiva.
hilo
Sinceramente, no he probado mucho algunas de las funciones del hilo . Quiero decir, lo usé mucho en términos de "instalar dependencias" mientras trabajaba en algunos proyectos, y eso es todo.
Yarn no viene con un instalador de Node.js , por lo que tendrás que instalarlo por separado. Significa que habría un paso adicional en sus canalizaciones de CI : tendría que configurar hilo antes de instalar las dependencias de su proyecto.
Administrar dependencias
Yarn tiene dos enfoques para instalar dependencias:
“ Instalaciones cero ” (predeterminado): crea una carpeta
.yarn
y enumera los paquetes en archivosyarn.lock
y.pnp.cjs
.
Uno normal, similar a npm , almacena las dependencias en
node_modules
y las enumera en el archivoyarn.lock
.
ℹ️ Los archivos de bloqueo de hilo almacenan información sobre los registros de todos los paquetes enumerados SÓLO si utiliza el método de instalación antiguo (normal).
⚠️ Tenga en cuenta que " Zero Installs " parece almacenar paquetes en el caché local y proporcionar enlaces a sus archivos de bloqueo:
Puede ser importante para usted si tiene una canalización Dockerfile o CI donde instala dependencias en un entorno limpio y luego desea moverlas a otro (deberá copiar tanto la carpeta .yarn
como el caché local).
Dado que el enfoque predeterminado para hilo ahora es " Instalaciones cero " y tiene mejor rendimiento que el enfoque anterior, registraremos puntos de referencia solo con este enfoque.
Generar archivos de bloqueo sin caché
Tomóyarn.lock
e instale dependencias sin caché.
Comando utilizado:
yarn install
Instalar dependencias de archivos de bloqueo existentes sin ningún caché
Tomó
Comando utilizado:
yarn install --frozen-lockfile
Instalar dependencias de archivos de bloqueo existentes con caché global
Tomó
Comando utilizado:
yarn install --frozen-lockfile
Administrar espacios de trabajo
Pude crear un espacio de trabajo y administrar dependencias para todos los proyectos a la vez y para proyectos específicos por separado.
Funciones del espacio de trabajo que utilicé hasta ahora:
- Instale dependencias para todos los proyectos dentro del espacio de trabajo.
- Instalar dependencias para un único proyecto específico.
- Ejecute un único script para todos los proyectos a la vez de forma recursiva.
La documentación está bien, pero los nombres de los comandos y las banderas son algo confusos.
Por ejemplo, debo ejecutar esto para ejecutar el script test
en la raíz ( . ) y el proyecto b2b
anidado:
yarn workspaces foreach -A --include '{.,b2b}' run test
En comparación con npm :
npm run test --workspace=b2b --include-workspace-root
pnpm
pnpm actualmente está de moda: muchas empresas y proyectos de código abierto lo utilizan .
Al igual que Yarn , pnpm no viene con un instalador de Node.js , por lo que deberá instalarlo por separado. Significa que habrá un paso adicional en sus canalizaciones de CI : tendrá que configurar pnpm antes de instalar las dependencias de su proyecto.
Administrar dependencias
pnpm se considera un " administrador de paquetes rápido y eficiente en el espacio en disco " ...
De hecho, estoy de acuerdo con la afirmación de "eficiente espacio en disco" en términos de gestión de dependencias localmente.
De forma predeterminada, pnpm elimina las duplicaciones de las dependencias compartidas. pnpm crea enlaces simbólicos para los paquetes que se utilizan en múltiples dependencias. es decir, si los paquetes a
y b
usan el paquete c
como dependencia, pnpm almacenará el paquete c
como una copia única y creará enlaces simbólicos para los paquetes a
y b
. De esa manera, el administrador de paquetes no crea copias impresas y ahorra memoria en su SSD/HDD.
ℹ️ pnpm-lock.yaml
no almacena información sobre los registros de los paquetes enumerados.
⚠️ Tenga en cuenta que pnpm a veces almacena dependencias en la caché global, en lugar de mantenerlo como proyecto.
Genere pnpm-lock.yaml sin ningún caché
Tomópnpm-lock.yaml
e instale dependencias sin ningún caché.
Comando utilizado:
pnpm install
Instalar dependencias desde pnpm-lock.yaml sin caché global
Tomópnpm-lock.yaml
sin caché.
Comando utilizado:
pnpm i --frozen-lockfile
Instalar dependencias del archivo de bloqueo existente con caché global
Tomópnpm-lock.yaml
con caché global.
Comando utilizado:
pnpm i --frozen-lockfile
Administrar espacios de trabajo
Ahora, ahí es donde las cosas se vuelven realmente interesantes...
pnpm tiene muchas opciones de configuración, ¡pero algunas funciones principales simplemente no funcionan!
Repasemos un par de errores que enfrenté:
instalación pnpm --filtro
Es importante poder instalar dependencias solo para proyectos específicos; es bastante útil para monorepos cuando crea canalizaciones relacionadas con proyectos específicos dentro del espacio de trabajo.
es decir, imagina que tienes en tu espacio de trabajo:
- una aplicación web,
- servidor de fondo,
- proyecto de prueba (pruebas de extremo a extremo).
Todos estos son proyectos npm separados, pero son parte del mismo repositorio ☝️
Ahora desea que una canalización ejecute pruebas de un extremo a otro únicamente. Entonces, solo necesitas dependencias de prueba de un extremo a otro, ¿verdad?
Bueno, no podrás hacer eso: ¡pnpm te obliga a instalar dependencias para todo el espacio de trabajo!
Se suponía que pnpm install --filter <project-name>
instalaría dependencias solo para proyectos seleccionados, pero no funciona.
Hay un error de hace un año y recientemente se cerró con una solución que no funciona.
instalación recursiva = falso
pnpm instala de forma predeterminada dependencias para todo el espacio de trabajo (todos los proyectos) cuando ejecuta pnpm install
Puede alternar este comportamiento si configura recursive-install=false
en .npmrc
en la raíz de su espacio de trabajo.
PERO introduce otro error que ya tiene casi 2 años .
espacio de trabajo compartido-lockfile=false
pnpm almacena de forma predeterminada la lista de dependencias en un único archivo de bloqueo (igual que npm y Yarn ).
También puede alternar este comportamiento si configura shared-workspace-lockfile=false
en .npmrc
en la raíz de su espacio de trabajo.
Eso nos permitiría mantener la función del espacio de trabajo y usar el indicador --ignore-workspace
para instalar dependencias para un proyecto específico.
De todos modos, esta configuración introduce un par de problemas más:
eslint
ytsc --noEmit
arrojan un error "JavaScript sin memoria" en mis canalizaciones de GitHub Actions .
Algunas de las dependencias se almacenan en la caché global y tienen enlaces simbólicos en
node_modules/.pnpm
.
Resultados de la comparación de rendimiento
# | npm | hilo | pnpm |
---|---|---|---|
Generar un archivo de bloqueo | 60 seg | 16,5 segundos | 31 seg |
Instalar dependencias sin caché | 18 seg | 11 seg | 8 seg |
Instalar dependencias con caché global | 8 seg | 8 seg | 5 segundos |
Según el punto de referencia anterior, npm es el administrador de paquetes más lento ☝️
De todos modos, interpretemos estos resultados…
Generar un archivo de bloqueo
Es un caso raro. Por lo general, se crea un archivo de bloqueo al inicializar el proyecto y luego se expande cuando instala/actualiza paquetes.
Teniendo esto en cuenta, no parece algo muy importante en lo que confiar al elegir un administrador de paquetes.
Instalar dependencias
En la mayoría de los casos, sus proyectos mantienen una lista específica de dependencias y rara vez agrega o elimina algo.
Lo más probable es que cambies las versiones de tus paquetes de vez en cuando; estos cambios son pequeños y reutilizarás el resto de los paquetes del caché.
En otras palabras, el caso de uso común es: buscar nuevos paquetes del registro de paquetes y tomar el resto del caché.
pnpm (5-8 segundos) es casi el doble de rápido que npm (8-18 segundos) con hilo (8-11 segundos) en el medio.
Conclusión
Hechos
- pnpm es de hecho un administrador de paquetes “rápido y eficiente en disco” ; ¡está bastante claro en la revisión actual!
- La característica del espacio de trabajo pnpm tiene errores y algunos de los errores no se han resuelto durante años.
- Tanto pnpm como Yarn requieren una configuración adicional en las canalizaciones de CI, mientras que npm no.
- Tanto pnpm como Yarn no almacenan información de registro de paquetes en sus archivos de bloqueo, mientras que npm sí.
Pensamientos del autor
Creo que pnpm hace el mejor trabajo si su requisito para el administrador de paquetes es tan simple como "instalar solo dependencias".
Aunque pnpm no viene con un instalador de Node.js listo para usar, es fácil de configurar en canalizaciones de CI con corepack o action existente .
Prefiero npm porque:
- es estable (especialmente espacios de trabajo),
- viene con Node.js y no requiere una configuración adicional en el proceso de CI,
- almacena registros de paquetes en
package-lock.json
para que pueda instalar dependencias con un único alcance desde diferentes registros.
Estas ventajas superan los segundos de velocidad y espacio en disco que ahorraría con hilo o pnpm .
¿Cuáles son sus criterios para elegir un administrador de paquetes? ¡No seas tímido y déjame saber tu opinión en la sección de comentarios a continuación! 👇😊