npm vs pnpm : comparaison du stockage, de la vitesse et des compromis dans un contexte réel
Cet article compare la manière dont npm et pnpm gèrent le stockage des dépendances, la vitesse d’installation ainsi que les workflows de monorepo afin de vous aider à choisir l’outil adapté à votre projet.
Si vous avez passé du temps à développer des applications avec React, Next.js, Node.js ou tout autre framework JavaScript moderne, il est fort probable que vous ayez tapé cette commande plus souvent qu’il n’est possible de le compter :
npm install
Elle fonctionne simplement. Tout le monde la reconnaît. Presque tous les tutoriels en ligne s’appuient sur elle.
Puis, à un moment donné, quelqu’un vous dit quelque chose comme :
"Pourquoi continuez-vous à utiliser npm ? Utilisez plutôt pnpm."
Alors vous essayez pnpm.
Et bientôt, vous vous demandez :
pnpm représente-t-il vraiment une amélioration, ou s’agit-il encore d’un de ces débats sur les outils JavaScript qui disparaissent au bout de quelques mois ?
C’est une question légitime.
Npm n’est en aucun cas défectueux. Il est familier, fiable et fourni automatiquement avec Node.js. Quitter npm nécessite une véritable justification.
Lorsque vous explorez le fonctionnement réel de chaque outil, vous réalisez que l’histoire véritable n’est pas simplement npm versus pnpm.
Tout se résume à la manière dont ils gèrent les dépendances, à l’espace disque qu’ils consomment, au comportement des installations dans différentes conditions, et au type de projet que vous développez.
Et la question la plus importante :
Lequel est le plus adapté à votre utilisation ?
npm et pnpm résolvent le même problème fondamental
Commençons par quelque chose d’évident.
Tant npm que pnpm sont des gestionnaires de paquets conçus pour le monde Node.js.
Tous deux téléchargent des paquets depuis le registre npm et respectent les mêmes conventions de package.json.
Supposons que votre projet ait besoin de React. Vous pouvez l’installer à l’aide de npm :
npm install react
Ou vous pouvez opter pour pnpm à la place :
pnpm add react
Quoi qu’il en soit, React finit par être installé.
Où ils divergent vraiment : la manière dont les dépendances sont stockées
node_modules indépendante contenant les paquets dont il a besoin.
En termes simples, au lieu de dupliquer le même paquet à chaque fois pour chaque projet, pnpm peut réutiliser une copie déjà présente dans son stock central.
Imaginez cela ainsi :
Project A ──┐
Project B ──┤
Project C ──┼── Shared package store
Project D ──┤
Project E ──┘
Le mécanisme réel derrière cela est plus complexe que ne le suggère ce schéma simplifié, mais c’est le concept de base qui importe ici.
pnpm a été conçu pour minimiser les copies redondantes.
Et si vous gérez plusieurs projets en même temps, ce choix de conception peut réduire significativement l’utilisation du disque.
pnpm installe-t-il vraiment les choses plus rapidement ?
C’est généralement la première chose que veulent savoir les développeurs.
La réponse honnête :
Souvent, oui — mais pas systématiquement.
De nombreux tests de performance montrent que pnpm surpasse npm en termes de vitesse.
Cependant, la vitesse d’installation dépend de nombreuses variables.
Votre connexion Internet joue un rôle important.
Même le matériel de votre disque a une influence.
Le nombre de paquets sur lesquels votre projet dépend est également crucial.
Le fait que ces paquets soient déjà en mémoire cache localement fait une différence.
La taille du projet entre aussi en compte.
Même une installation complète par rapport à une réinstallation de quelque chose que vous avez déjà téléchargé peut donner des résultats très différents.
L’architecture de pnpm est conçue pour un téléchargement et un liage efficaces, et comme elle gère un stock partagé, les paquets que vous avez déjà localement peuvent être simplement réutilisés au lieu d’être téléchargés à nouveau.
C’est dans ce cas que ses avantages se manifestent vraiment.
Les installations « froides » versus les installations « chaudes » font une vraie différence
C’est un détail qui est souvent négligé lorsque les gens comparent les gestionnaires de paquets.
Disons que vous installez un paquet pour la toute première fois.
Vous n’avez pas d’autre choix que de le télécharger depuis zéro.
C’est essentiellement un scénario de démarrage à froid.
Imaginons maintenant que ce même paquet existe déjà dans un autre projet sur votre machine.
C’est un point de départ complètement différent.
C’est précisément là que le stock partagé de pnpm devient utile.
Au lieu de traiter chaque projet comme un système isolé, pnpm peut récupérer des paquets déjà stockés localement.
Ainsi, si vous créez régulièrement de nouveaux projets, que vous effacez les dossiers node_modules, que vous réinstallez fréquemment les dépendances ou que vous alternez entre plusieurs dépôts, l’efficacité de pnpm devient beaucoup plus évidente avec le temps.
Mais si votre workflow concerne simplement un projet modeste où vous installez les dépendances une seule fois, la différence ne vous surprendra probablement pas.
C’est pourquoi je m’abstiendrais de prétendre :
« pnpm est toujours l’option la plus rapide. »
Une formulation plus précise serait :
pnmn a tendance à être considérablement plus efficace, en particulier dans les workflows basés sur des installations répétées ou des arbres de dépendances lourds.
npm a évolué bien au-delà de sa réputation passée
Un autre point à souligner ici.
Beaucoup de discussions sur npm versus pnpm dépeignent npm comme un outil obsolète que les développeurs auraient dû abandonner depuis longtemps.
Cette description n’est pas vraiment exacte.
npm a fait de grands progrès.
La version actuelle prend en charge des fonctionnalités telles que les espaces de travail, les fichiers lockfile et npm ci pour des installations reproductibles au sein de pipelines CI.
À titre d’exemple :
npm ci
Ce commandement est utilisé régulièrement lorsque l’on souhaite une installation propre, basée sur un fichier lockfile.
Dire que npm est lent, dépassé ou mal conçu n’est pas justifié.
Ce reste un choix tout à fait fiable pour une grande partie des projets existants.
Ce qui distingue pnpm, c’est qu’il a adopté des choix de conception axés spécifiquement sur l’efficacité, et ces choix deviennent de plus en plus évidents à mesure que votre projet grandit.
Une autre différence rencontrée par les développeurs : l’isolation des dépendances
Ce point n’est pas immédiatement évident, surtout si vous êtes nouveau dans cet écosystème.
Imaginons ce scénario : votre application dépend du paquet A. Le paquet A, à son tour, dépend du paquet B. Vous n’avez jamais installé B vous-même — vous ne l’avez même jamais listé dans votre propre manifeste. Pourtant, en raison du fonctionnement de node_modules, votre code peut encore require ou import B directement, et cela fonctionnera.
Pendant un certain temps, rien ne semble anormal.
Alors, le package A se met à jour et remplace ses dépendances. B n’est plus à l’endroit où votre code s’y attendait, et soudainement votre application génère une erreur inattendue.
Cette situation a un nom : une dépendance fantôme. Vous vous appuyez sur quelque chose qui n’a jamais vraiment été destiné à être utilisé comme dépendance.
pnpm évite cela par conception. Sa structure par défaut est bien plus stricte quant à ce qu’un package peut réellement voir, ce qui rend beaucoup plus difficile pour votre projet de s’appuyer sur quelque chose qu’il n’a jamais déclaré explicitement comme dépendance.
C’est une garantie véritablement précieuse. Elle vous oblige à être honnête quant aux besoins réels de votre application, plutôt que de profiter d’un hasard lié à l’organisation des fichiers. Ce type de rigueur a tendance à avoir plus d’importance à long terme que de gagner quelques secondes lors de l’installation.
Le scénario où pnpm brille vraiment : les monorepos
C’est probablement le cas le plus convaincant pour opter pour pnpm.
Imaginez un codebase d’entreprise structuré de la manière suivante :
my-project/
│
├── apps/
│ ├── web/
│ └── admin/
│
├── packages/
│ ├── ui/
│ ├── utils/
│ └── config/
│
└── package.json
Il y a plusieurs applications ainsi que quelques paquets internes partagés, tous réunis dans un seul repository. Cette configuration est ce que l’on appelle un monorepo.
Npm prend en charge les espaces de travail, donc il est tout à fait possible de créer un monorepo avec npm. Cependant, pnpm a consacré beaucoup plus d’efforts spécifiquement aux outils pour les monorepos. Il offre des fonctionnalités telles que son protocole d’espace de travail, des flags de filtrage pour exécuter des commandes sur des paquets spécifiques, ainsi qu’un modèle de dépendances conçu pour les repositories multi-paquets — tout cela permettant de rendre un grand codebase nettement plus facile à gérer.
Si vous gérez un petit projet personnel, tout cela n’a pas vraiment d’importance pour vous.
Mais si vous gérez un dépôt contenant plusieurs applications et des dizaines de paquets partagés internes, ces outils deviennent beaucoup plus pertinents.
Passer de npm à pnpm est une petite modification
Une raison courante pour laquelle les développeurs évitent d’essayer pnpm est l’idée qu’ils devront apprendre un ensemble entièrement nouveau de commandes.
C’est en réalité pas le cas. La plupart des commandes courantes correspondent presque un par un.
L’installation de dépendances avec npm se fait comme ceci :
npm install
Avec pnpm, c’est :
pnpm install
Ajout d’un paquet avec npm :
npm install axios
devient ceci avec pnpm :
pnpm add axios
Ajout d’une dépendance de développement avec npm :
npm install -D typescript
devient :
pnpm add -D typescript
Désinstallation d’un paquet avec npm :
npm uninstall axios
devient :
pnpm remove axios
npm run dev
on peut le raccourcir en :
pnpm dev
Et si vous êtes déjà à l’aise avec npx, pnpm dispose de son propre équivalent :
pnpm dlx
Ainsi, la courbe d’apprentissage est ici minimale.
Cas où npm reste le choix le plus logique
Si vous présentez JavaScript ou Node.js à quelqu’un pour la première fois, npm est le choix naturel pour commencer. Non pas parce qu’il est techniquement supérieur à tous égards — mais simplement parce qu’il est fourni par défaut, et que les débutants ont déjà beaucoup à assimiler sans devoir ajouter une décision concernant un gestionnaire de paquets en plus.
Si un tutoriel vous demande d’exécuter :
npm install express
vous devriez pouvoir simplement le taper et continuer à apprendre le concept réel qui est enseigné.
Npm est également le choix approprié lorsque vous travaillez sur un codebase déjà construite autour de lui. Il n’y a guère de raison d’insister :
« L’équipe a toujours utilisé npm, mais pnpm est préféré ici, alors transformons toute la configuration. »
Dans un environnement d’équipe, il vaut mieux être cohérent avec ce que les autres utilisent plutôt que d’optimiser en fonction des préférences individuelles.
Cas où pnpm devient plus judicieux
pnpm devient de plus en plus attrayant à mesure que le projet ou le flux de travail gagne en ampleur.
Si vous gérez régulièrement plusieurs projets JavaScript en même temps, le stockage adressable partagé par pnpm peut réduire l’utilisation redondante de l’espace disque entre eux. Lorsque votre arbre de dépendances est volumineux et complexe, des installations plus rapides et plus légères deviennent cruciales. Et si vous gérez un monorepo, les fonctionnalités de workspace de pnpm méritent une réflexion sérieuse.
L’isolation des dépendances est une autre raison de l’utiliser — si des limites strictes entre ce qui est déclaré et ce qui peut être utilisé sont vraiment importantes pour votre projet, pnpm les impose par défaut.
En termes simples : plus une configuration JavaScript devient complexe et en désordre, plus pnpm s’avère attrayant.
Alors, lequel l’emporte en vitesse ?
Si l’on cherche une réponse unique, pnpm présente généralement un avantage en termes d’efficacité d’installation, surtout lorsque son stock partagé contient déjà les paquets en mémoire locale.
Néanmoins, il ne serait pas exact de prétendre quelque chose comme :
"pnpm est exactement deux fois plus rapide que npm."
Ce type d’affirmation simplifie trop les choses. Les résultats des benchmarks varient considérablement en fonction des conditions. Exécuter une installation complètement neuve via une connexion réseau rapide n’est pas comparable à la réinstallation de paquets sur une machine qui en a déjà la plupart en mémoire locale. De plus, un environnement CI se comporte différemment d’une machine locale.
Ainsi, si le graphique d’un benchmark est la seule raison qui pousse à envisager un changement de gestionnaire de paquets, il vaut mieux examiner son propre flux de travail avant de prendre une telle décision.
Mon choix
Pour un petit projet React, npm suffit sans aucun problème.
C’est également le cas pour un projet d’apprentissage — npm est parfait.
Si vous rejoignez un codebase d’équipe existant, utilisez ce que l’équipe a déjà standardisé.
Cependant, pour un grand monorepo, pnpm devient une alternative sérieuse.
Et si vous travaillez sur une machine où vous passez constamment d’un projet JavaScript à un autre, pnpm s’avère généralement être le choix le plus pratique.
Tout cela explique pourquoi il n’y a pas de gagnant universel dans ce cas.
Ne changez pas juste parce que pnpm est à la mode
Ce pourrait être le point le plus important de toute cette comparaison.
Vous n’avez pas besoin de migrer tous vos projets existants de npm vers pnpm simplement parce que ce dernier est souvent mentionné dans les discussions des développeurs en ligne.
Et vous n’avez certainement pas besoin de changer parce que quelqu’un insiste :
"npm est mort."
C’est faux. Les deux outils sont activement maintenus, tous deux disposent d’écosystèmes matures, et ils sont parfaitement capables de gérer des projets JavaScript modernes.
La vraie question n’est pas « quel gestionnaire de paquets est objectivement le meilleur ». C’est plutôt « quel gestionnaire de paquets correspond à ma façon de travailler réelle ? »
Si vous développez de petites applications, que vous apprenez le langage ou que vous travaillez au sein d’une équipe qui utilise déjà npm, rester avec npm est un choix tout à fait raisonnable.
En revanche, si vous gérez de grands projets, plusieurs répertoires ou des monorepos et que vous souhaitez un stockage plus efficace des dépendances ainsi que des installations plus rapides, alors il vaut la peine d’essayer pnpm.
Conclusions
Lorsque j’ai entrepris cette comparaison entre npm et pnpm, il semblait y avoir un verdict clair et simple : npm serait l’option dépassée, tandis que pnpm représenterait une amélioration rapide.
La réalité s’est avérée plus nuancée que cela.
Le point fort principal de npm réside dans sa simplicité et dans le fait que presque tout le monde le connaît déjà. C’est l’option par défaut pour de bonnes raisons.
Les forces principales de pnpm sont son modèle de stockage des dépendances, son efficacité lors des installations, ainsi que les outils qu’il propose pour les projets à grande échelle.
Ainsi, si vous êtes nouveau en JavaScript, ne vous tourmentez pas pour ce choix — utilisez simplement npm et commencez à développer.
Si vous maîtrisez déjà bien Node.js et que vos projets prennent de l’ampleur, essayez pnpm pour voir s’il améliore votre flux de travail quotidien.
Finalement, c’est pas le gestionnaire de paquets que vous choisissez qui fait d’une application une bonne application.
C’est votre code qui le fait.
Lectures complémentaires
- Référence des commandes Node.js pour le développement local et les serveurs de production — Une référence des commandes facile à consulter couvrant la gestion des versions de Node.js, les gestionnaires de paquets, la configuration de l’environnement, le débogage, PM2, ainsi que les déploiements Linux sans interruption.