paint-brush
Pourquoi vous n'avez pas besoin de PNPM et de YARNby@bormando

Pourquoi vous n'avez pas besoin de PNPM et de YARN

Dmitrii Bormotov9m2024/07/23
Read on Terminal Reader

npm est un gestionnaire de packages par défaut pour l'écosystème **Node.js**. Il est fourni avec le package d'installation, il est donc pratiquement prêt à être utilisé lorsque vous installez **Node.js** sur votre ordinateur (ou dans n'importe quel fournisseur **CI** si vous y configurez **Node.js**). Il est stable et sa vitesse est comparable à celle des autres gestionnaires de paquets.
featured image - Pourquoi vous n'avez pas besoin de PNPM et de YARN
Dmitrii Bormotov HackerNoon profile picture
0-item

Bonjour à tous!


Je suis sûr que vous avez vu des projets Node.js utiliser différents gestionnaires de packages, c'est-à-dire :



J'ai vu cela moi-même et j'ai travaillé avec tout ce qui précède, mais j'ai toujours eu une question en tête : qu'est-ce qui pousse les personnes/équipes à utiliser fil ou pnpm au lieu de npm ? Quels sont les avantages ? Y a-t-il des inconvénients ?


Eh bien… Découvrons-le !

Règles de comparaison des performances

J'ai décidé de comparer npm , fil et pnpm en termes de leur « vitesse »…


Vous verrez 3 mesures ci-dessous :


  1. Générez un fichier de verrouillage sans aucun cache.


  2. Installez les dépendances à partir des fichiers de verrouillage existants sans aucun cache.


  3. Installez les dépendances des fichiers de verrouillage existants avec le cache global.


Il existe deux types de cache :


  1. Mondial.

    Généralement stocké dans le répertoire personnel de l'utilisateur (fe, ~/.yarn/berry/cache ).


  2. Locale.

    Stocké dans le répertoire du projet (par exemple, <project-dir>/.yarn ).


Bien que les cas d'utilisation n°2 et n°3 soient les cas d'utilisation les plus courants d'après mon expérience, j'ai également pris le n°1 juste au cas où (bien que ce soit un cas très rare).


J'ai utilisé un exemple de projet de create-react-app comme exemple de benchmark.

npm

C'est un gestionnaire de packages par défaut pour l'écosystème Node.js - que dire d'autre ? Il est livré avec le package d'installation, il est donc fondamentalement prêt à être utilisé lorsque vous installez Node.js sur votre machine (ou dans n'importe quel fournisseur CI si vous y configurez Node.js ).


C'est un énorme « avantage » à mon avis : vous n'avez pas besoin de l'installer séparément !


Rien d'exceptionnel là-bas - ça marche juste ! Et je n'ai vu aucun bug majeur au fil des ans - il semble assez stable et fait le travail.


Les fonctionnalités de npm que j'ai utilisées jusqu'à présent :


  1. Gérer les dépendances (installer, supprimer, mettre à jour)
  2. Publier des packages (privés, publics)
  3. Forfaits lien-local
  4. Gérer les espaces de travail.

Gérer les dépendances

npm stocke les dépendances dans le dossier node_modules de la racine de votre projet. Assez simple.


ℹ️ package-lock.json stocke des informations sur les registres pour les packages répertoriés - cela s'avère TRÈS pratique si vous avez des packages d'une seule portée, c'est-à-dire @example-company dans différents registres (par exemple - npm & GitHub Packages ) :


entrée package-lock.json


Voyons maintenant comment il se comporte en termes de vitesse d'installation…

Générer package-lock.json sans aucun cache

Générez package-lock.json et installez les dépendances sans aucun cache


Ça a pris 1 minute pour que npm génère un package-lock.json et installe les dépendances sans aucun cache.


Commande utilisée :

 npm i

Installer les dépendances à partir de package-lock.json sans aucun cache

Installer les dépendances à partir de package-lock.json sans aucun cache


Ça a pris 18 secondes pour que npm installe les dépendances de package-lock.json sans aucun cache.


Commande utilisée :

 npm ci

Installer les dépendances à partir de package-lock.json avec le cache global

Installer les dépendances à partir de package-lock.json avec le cache global


Ça a pris 8 secondes pour que npm installe les dépendances de package-lock.json avec le cache global.


Commande utilisée :

 npm ci

Gérer les espaces de travail

J'ai pu créer un espace de travail et gérer les dépendances pour l'ensemble de l'espace de travail à la fois et pour des projets spécifiques séparément.


En d’autres termes, le travail est effectué sans aucun bug/problème, et la documentation officielle est assez simple.


Fonctionnalités de Workspace que j'ai utilisées jusqu'à présent :


  1. Installez les dépendances pour tous les projets dans l'espace de travail.
  2. Installez les dépendances pour un seul projet spécifique.
  3. Exécutez un seul script pour tous les projets à la fois et de manière récursive.

fil

Honnêtement, je n’ai pas beaucoup essayé certaines fonctionnalités du fil . Je veux dire, je l'ai beaucoup utilisé pour « installer des dépendances » en travaillant sur certains projets, et c'est tout à fait ça.


Yarn n'est pas fourni avec un programme d'installation Node.js , vous devrez donc l'installer séparément. Cela signifie qu'il y aurait une étape supplémentaire dans vos pipelines CI : vous devrez configurer Yarn avant d'installer les dépendances de votre projet.

Gérer les dépendances

Yarn a deux approches pour installer les dépendances :


  1. « Zéro installation » (par défaut) - crée le dossier .yarn et répertorie les packages dans les fichiers yarn.lock et .pnp.cjs .


  2. Un standard - similaire à npm , stocke les dépendances dans node_modules et les répertorie dans le fichier yarn.lock .


ℹ️ Les fichiers Yarn Lock stockent des informations sur les registres pour tous les packages répertoriés UNIQUEMENT si vous utilisez l'ancienne approche d'installation (normale).


⚠️ Gardez à l'esprit que « Zéro installation » semble stocker les packages dans le cache local et fournir des liens vers vos fichiers de verrouillage :


Liens vers les packages

Cela peut être important pour vous si vous disposez d'un pipeline Dockerfile ou CI dans lequel vous installez des dépendances dans un environnement propre et que vous souhaitez ensuite les déplacer vers un autre (vous devrez copier à la fois le dossier .yarn et le cache local).


Étant donné que l'approche par défaut pour le fil est désormais « Zéro installation » et offre de meilleures performances que l'ancienne approche, nous allons enregistrer des benchmarks avec cette approche uniquement.

Générer des fichiers de verrouillage sans aucun cache

Générer des fichiers de verrouillage avec du fil et installer les dépendances


Ça a pris 16,5 secondes pour que Yarn génère un fichier yarn.lock et installe les dépendances sans cache.


Commande utilisée :

 yarn install

Installer les dépendances à partir de fichiers de verrouillage existants sans aucun cache

Installer les dépendances avec l'approche "Zero Install" et sans aucun cache


Ça a pris 11 secondes pour que Yarn installe les dépendances avec l'approche « Zero Install » et sans aucun cache.


Commande utilisée :

 yarn install --frozen-lockfile

Installer les dépendances à partir de fichiers de verrouillage existants avec le cache global


Installer les dépendances avec l'approche "Zero Install" et le cache global


Ça a pris 8 secondes pour que Yarn installe les dépendances avec l'approche « Zero Install » et le cache global.


Commande utilisée :

 yarn install --frozen-lockfile

Gérer les espaces de travail

J'ai pu créer un espace de travail et gérer les dépendances pour tous les projets à la fois et pour des projets spécifiques séparément.


Fonctionnalités de Workspace que j'ai utilisées jusqu'à présent :


  1. Installez les dépendances pour tous les projets dans l'espace de travail.
  2. Installez les dépendances pour un seul projet spécifique.
  3. Exécutez un seul script pour tous les projets à la fois et de manière récursive.


La documentation est bonne, mais les noms de commandes et les indicateurs prêtent quelque peu à confusion.


Par exemple, je dois exécuter ceci pour exécuter le script test dans la racine ( . ) et le projet b2b imbriqué :


 yarn workspaces foreach -A --include '{.,b2b}' run test


En comparaison avec npm :


 npm run test --workspace=b2b --include-workspace-root

pnpm

pnpm est actuellement à la mode - de nombreuses entreprises et projets open source l'utilisent .


Tout comme Yarn , pnpm n'est pas fourni avec un programme d'installation Node.js , vous devrez donc l'installer séparément. Cela signifie qu'il y aura une étape supplémentaire dans vos pipelines CI : vous devrez configurer pnpm avant d'installer les dépendances de votre projet.

Gérer les dépendances

pnpm est considéré comme « Gestionnaire de paquets rapide et efficace en termes d'espace disque »


En effet, je suis d'accord avec l'affirmation « efficacité de l'espace disque » en termes de gestion locale des dépendances.


Par défaut, pnpm déduplique les dépendances partagées. pnpm crée des liens symboliques pour les packages utilisés dans plusieurs dépendances. c'est-à-dire que si les packages a et b utilisent le package c comme dépendance, pnpm va stocker le package c en une seule copie et créer des liens symboliques pour les packages a et b . De cette façon, le gestionnaire de packages ne crée pas de copies papier et économise de la mémoire sur votre SSD/HDD.


ℹ️ pnpm-lock.yaml ne stocke pas d'informations sur les registres pour les packages répertoriés.


⚠️ Gardez à l'esprit que pnpm stocke parfois les dépendances dans le cache global, au lieu d'en faire un projet.

Générez pnpm-lock.yaml sans aucun cache

Générer pnpm-lock.yaml


Ça a pris 31 secondes pour que pnpm génère un pnpm-lock.yaml et installe les dépendances sans aucun cache.


Commande utilisée :

 pnpm install

Installer les dépendances à partir de pnpm-lock.yaml sans cache global

Installer les dépendances à partir de pnpm-lock.yaml sans cache global


Ça a pris 16 secondes pour que pnpm installe les dépendances de pnpm-lock.yaml sans cache.


Commande utilisée :

 pnpm i --frozen-lockfile


Installer les dépendances à partir d'un fichier de verrouillage existant avec le cache global

Installer les dépendances de pnpm-lock-yaml avec cache


Ça a pris 5 secondes pour que pnpm installe les dépendances de pnpm-lock.yaml avec le cache global.


Commande utilisée :

 pnpm i --frozen-lockfile

Gérer les espaces de travail

Maintenant, c'est là que les choses deviennent vraiment intéressantes…


pnpm a de nombreuses options de configuration, mais certaines fonctionnalités de base ne fonctionnent tout simplement pas !


Passons en revue quelques bugs que j'ai rencontrés :

pnpm installer --filtre

Il est important de pouvoir installer des dépendances pour des projets spécifiques uniquement - c'est très utile pour les monorepos lorsque vous créez des pipelines liés à des projets spécifiques dans l'espace de travail.


c'est-à-dire, imaginez que vous avez dans votre espace de travail :


  • une application web,
  • serveur principal,
  • projet de test (tests de bout en bout).


Ce sont tous des projets npm distincts, mais ils font partie du même dépôt ☝️


Désormais, vous souhaitez qu’un pipeline exécute uniquement des tests de bout en bout. Donc, vous n’avez besoin que de dépendances de test de bout en bout, n’est-ce pas ?


Eh bien, vous ne pourrez pas faire ça - pnpm vous oblige à installer des dépendances pour l'ensemble de l'espace de travail !


pnpm install --filter <project-name> était censé installer les dépendances pour les projets sélectionnés uniquement, mais cela ne fonctionne pas.


Il y a un bug vieux d'un an et il a été récemment fermé avec un correctif qui ne fonctionne pas.

installation récursive = false

pnpm installe par défaut les dépendances pour l'ensemble de l'espace de travail (tous les projets) lorsque vous exécutez pnpm install


Vous pouvez alterner ce comportement si vous définissez recursive-install=false dans .npmrc à la racine de votre espace de travail.


MAIS cela introduit un autre bug qui date déjà de presque 2 ans .

partage-workspace-lockfile=false

pnpm stocke par défaut la liste des dépendances dans un seul fichier de verrouillage (identique à npm et Yarn ).


Vous pouvez également alterner ce comportement si vous définissez shared-workspace-lockfile=false dans .npmrc à la racine de votre espace de travail.


Cela nous permettrait de conserver la fonctionnalité d'espace de travail et d'utiliser l'indicateur --ignore-workspace pour installer des dépendances pour un projet spécifique.


Quoi qu'il en soit, ce paramètre introduit quelques problèmes supplémentaires :


  1. eslint et tsc --noEmit génèrent une erreur « Heap JavaScript Out of Memory » dans mes pipelines GitHub Actions .


  2. Certaines dépendances sont stockées dans le cache global et liées par un lien symbolique dans node_modules/.pnpm .

Résultats de comparaison des performances

#

npm

fil

pnpm

Générer un fichier de verrouillage

60 secondes

16,5 secondes

31 secondes

Installer les dépendances sans aucun cache

18 secondes

11 secondes

8 secondes

Installer les dépendances avec le cache global

8 secondes

8 secondes

5 secondes


Selon le benchmark ci-dessus, npm est le gestionnaire de paquets le plus lent ☝️


Quoi qu’il en soit, interprétons ces résultats…

Générer un fichier de verrouillage

C'est un cas rare. Habituellement, un fichier de verrouillage est créé lors de l'initialisation du projet, puis se développe lorsque vous installez/mettez à jour des packages.


Dans cet esprit, il ne semble pas être une chose très importante sur laquelle s'appuyer lorsque vous choisissez un gestionnaire de packages.

Installer les dépendances

Dans la plupart des cas, vos projets conservent une liste spécifique de dépendances et vous ajoutez/supprimez rarement quelque chose.


Très probablement, vous modifierez les versions de vos packages de temps en temps - ces modifications sont minimes et vous réutiliserez le reste des packages du cache.


En d’autres termes, le cas d’utilisation courant est le suivant : récupérer de nouveaux packages dans le registre des packages et récupérer le reste dans le cache.


pnpm (5-8 sec) est presque deux fois plus rapide que npm (8-18 sec) avec du fil (8-11 sec) au milieu.

Conclusion

Faits

  • pnpm est en effet un gestionnaire de paquets « rapide et efficace sur le disque » - c'est assez clair dans la revue actuelle !


  • La fonctionnalité d'espace de travail pnpm est boguée et certains bogues ne sont pas résolus depuis des années.


  • pnpm et Yarn nécessitent une configuration supplémentaire dans les pipelines CI, contrairement à npm .


  • pnpm et Yarn ne stockent pas les informations de registre des packages dans leurs fichiers de verrouillage, contrairement à npm .

Pensées de l'auteur

Je pense que pnpm fait le meilleur travail si vos exigences en matière de gestionnaire de paquets sont aussi simples que « installer uniquement les dépendances ».


Même si pnpm n'est pas fourni avec un programme d'installation Node.js prêt à l'emploi, il est facile à configurer dans les pipelines CI avec un corepack ou une action existante .


Je préfère npm , parce que :


  • c'est stable (surtout les espaces de travail),


  • est livré avec Node.js et ne nécessite pas de configuration supplémentaire dans le pipeline CI,


  • stocke les registres de packages dans package-lock.json afin que vous puissiez installer des dépendances avec une seule portée à partir de différents registres.


Ces avantages l'emportent sur les secondes de vitesse et d'espace disque que j'économiserais avec fil ou pnpm .


Quels sont vos critères de choix d’un gestionnaire de packages ? Ne soyez pas timide et faites-moi part de vos commentaires dans la section commentaires ci-dessous ! 👇😊