Mieux vaut utiliser pNPM (plutôt que NPM)

pNPM est (encore) un gestionnaire de paquets pour Node.

Ok, Ok !! Il existe déjà NPM (ou mieux Yarn), alors pourquoi changer !? Eh bien, pour des raisons de performances, évidemment 😎👌 D’après les métriques, pNPM est 2x plus rapide que NPM 🚀

Explication

Tout comme ses homologues, pNPM prend la sécurité très au sérieux en s’assurant de l’intégrité des dépendances utilisées par un (ou plusieurs *) projet(s) JavaScript, grâce à une stratégie de fichier « lock » (pnpm-lock.yaml).

*NB : À l’instar de NPM (et Yarn avant lui), pNPM supporte les projets monolithiques, ou plus communément appelés : « workspaces ».

Ce qu’on apprécie le plus à propos de pNPM c’est sa manière de gérer les node_modules. En effet, la grande différence de l’usage de ce gestionnaire de paquets réside dans l’organisation des dépendances.

NPM (et Yarn) dispose d’une arborescence de node_modules dite « aplatie » ; en d’autres termes, toutes les librairies se trouvent au même niveau… pNPM fonctionnent différemment en répertoriant les dépendances par liens physiques et symboliques.

De plus, pNPM conserve les librairies dans un seul et unique endroit sur le disque : le « store ». Ainsi, même si vous récupérez plusieurs versions d’une même dépendance, pNPM s’occupe de faire la différence entre elles, puis récupère seulement les changements nécessaires.

NB : Pour rappel, avec NPM, vous récupérez l’ensemble des dépendances à l’installation d’un projet, et cela pour chaque projet. De ce fait, chaque version est stockée indépendamment, prenant davantage de place en mémoire… Le store de pNPM, en plus d’être efficace, permet d’alléger votre espace disque.

Ce mode de fonctionnement rend pNPM plus robuste que ses concurrents, puisqu’il n’est pas permis d’utiliser une dépendance non enregistré dans le package.json.

En effet, avec un gestionnaire de paquets traditionnel, il est possible d’utiliser les librairies de manière implicite, à condition qu’elles soient récupérées à partir d’une autre dépendance.

Cas d'usage

Lors de la création d’un nouveau projet avec l’outil CLI « officiel » (pour le moment) de React : npx create-react-app my-project ; la plupart des librairies du projets sont embarquées dans la dépendance react-scripts. Il est donc possible d’utiliser ESLint ou encore Jest implicitement. ⚠️ SPOILER ALERT : ceci n’est pas une bonne pratique !!!

Ce type d’utilisation peut créer des problèmes majeurs sur des développement à venir / sur la maintenance applicative… Imaginons que react-scripts mette à jour l’une ou l’autre librairie, le comportement de vos tests unitaires (cf. Jest) serait impacté. Pire encore : quelle serait la conséquence de la suppression de Jest (au profit d’un autre test runner) ? L’utilisation de dépendances « transitives » n’est donc pas recommandé ! D’ailleurs, ceci est en partie l’histoire de left-pad

NB : Pour reproduire une mécanique de résilience (similaire à pNPM) pour NPM ou Yarn, vous pouvez utiliser dependency-check qui permet de s’assurer de la conformité de votre projet.

Migration

Convaincu par cette introduction ? Alors, il est temps d’entrer dans le vif du sujet ! La première étape pour migrer de NPM (ou Yarn) à pNPM est l’installation du gestionnaire de paquets : npm i -g pnpm (il existe d’autres méthodes alternatives).

Ensuite, dans un projet existant, possédant déjà un fichier package-lock.json (ou équivalent Yarn), il suffit de suivre l’instruction : pnpm import.

Enfin, vous pouvez supprimer vos node_modules pour les (re)récupérer à partir de pNPM : pnpm install

NB : Globalement, pNPM est basé sur l’API de NPM, ainsi les commandes pnpm install, pnpm config set ou encore pnpm run your:script sont entièrement supportées !

Prenons l’exemple du package.json suivant, et comparons l’avant / après utilisation du nouveau gestionnaire de paquets :

{
  "name": "react-only",
  "version": "0.0.1",
  "description": "React + DOM (Only)",
  "main": "index.js",
  "scripts": {
    "start": "echo \"¯\\_(ツ)_/¯\" && exit 0"
  },
  "dependencies": {
    "react": "~18.2.0",
    "react-dom": "~18.2.0"
  },
  "license": "Beerware"
}

À l’installation des dépendances ci-dessus avec NPM, vous vous retrouverez à avoir une structure « aplatie » au sein de votre projet :

/
├── node_modules/
│   ├── js-token
│   ├── loose-envify
│   ├── react
│   ├── react-dom
│   └── scheduler
├── package.json
└── package-lock.json

Arborescence de fichiers avec NPM

D’un autre côté, en utilisant pNPM pour installer react et react-dom, toutes les dépendances (ainsi que les dépendances indirectes) sont récupérées dans le dossier masqué .pnpm (et identifiées par version) ; seules les librairies spécifiques au projet sont présentes à la racine de node_modules (par un lien symbolique). Impossible donc d’appeler js-token, loose-envify ou encore scheduler directement !

/
├── node_modules/
│   ├── .pnpm/
│   │   ├── js-token@4.0.0
│   │   ├── loose-envify@1.4.0
│   │   ├── react@18.2.0
│   │   ├── react-dom@18.2.0
│   │   └── scheduler@0.23.0
│   ├── react -> .pnpm/react@18.2.0/node_modules/react
│   └── react-dom -> .pnpm/react-dom@18.2.0/node_modules/react-dom
├── package.json
└── pnpm-lock.yaml

Arborescence de fichiers avec pNPM

Après cela, le choix de pNPM paraît évident, si ce n’est que pour la lisibilité des node_modules. Rassurez-vous, vous ne serez pas le premier à migrer vers ce gestionnaire de paquets de nouvelle génération, des projets comme Prisma, Vue ou encore SvelteKit l’on fait, de même que Microsoft. Enjoy 👍

This website stores cookies on your computer. Cookie Policy