¡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!
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.
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:
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…
Tomópackage-lock.json
e instale dependencias sin ningún caché.
Comando utilizado:
npm i
Tomópackage-lock.json
sin ningún caché.
Comando utilizado:
npm ci
Tomópackage-lock.json
con caché global.
Comando utilizado:
npm ci
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:
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.
Yarn tiene dos enfoques para instalar dependencias:
“ Instalaciones cero ” (predeterminado): crea una carpeta .yarn
y enumera los paquetes en archivos yarn.lock
y .pnp.cjs
.
Uno normal, similar a npm , almacena las dependencias en node_modules
y las enumera en el archivo yarn.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.
Tomóyarn.lock
e instale dependencias sin caché.
Comando utilizado:
yarn install
Tomó
Comando utilizado:
yarn install --frozen-lockfile
Tomó
Comando utilizado:
yarn install --frozen-lockfile
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:
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 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.
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.
Tomópnpm-lock.yaml
e instale dependencias sin ningún caché.
Comando utilizado:
pnpm install
Tomópnpm-lock.yaml
sin caché.
Comando utilizado:
pnpm i --frozen-lockfile
Tomópnpm-lock.yaml
con caché global.
Comando utilizado:
pnpm i --frozen-lockfile
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é:
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:
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.
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 .
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
y tsc --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
.
# | 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…
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.
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.
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:
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! 👇😊