Les nouveaux utilisateurs de pnpm me posent souvent des questions sur la structure bizarre du dossier node_modules
que pnpm créé. Pourquoi n'est-il pas plat ? Où sont toutes les sous-dépendances ?
Je vais supposer que les lecteurs de cet article sont déjà familiers avec les
node_modules
plats créés par npm et Yarn. Si vous ne comprenez pas pourquoi npm 3 a dû commencer à utilisernode_modules
en v3, vous pouvez trouver un peu de préhistoire dans Pourquoi devrait-on utiliser pnpm ?.
Alors pourquoi les node_modules
de pnpm sont inhabituels ? Créons deux répertoires et éxecutons npm add express
dans l'un d'eux et pnpm add express
dans l'autre. Voilà ce que vous obtenez dans le node_modules
du premier répertoire:
.bin
accepts
array-flatten
body-parser
bytes
content-disposition
cookie-signature
cookie
debug
depd
destroy
ee-first
encodeurl
escape-html
etag
express
Vous pouvez voir tout le répertoire ici.
Et voici ce que vous obtenez dans les node_modules
créés par pnpm:
.pnpm
.modules.yaml
express
Vous pouvez vérifier ici.
Alors, où sont toues les dépendances ? Il y a qu'un seul dossier dans les node_modules
appelé .pnpm
et il y a un lien symbolique appelé express
. Et bien, nous n'avons installé que express
, c'est donc le seul package auquel votre application doit avoir accès
En savoir plus sur pourquoi la rigueur de pnpm est une bonne chose ici
Voyons ce qu'il y a à l'intérieur d'express
:
▾ node_modules
▸ .pnpm
▾ express
▸ lib
History.md
index.js
LICENSE
package.json
Readme.md
.modules.yaml
express
n'a pas de node_modules
? Où sont toutes les dépendances d'express
?
L'astuce est qu'express
n'est qu'un lien symbolique. Lorsque Node.js résout les dépendances, il utilise leurs emplacements réels, il ne conserve donc pas les liens symboliques. Mais où est l'emplacement réel d'express
, vous vous demandez ?
Ici: node_modules/.pnpm/express@4.17.1/node_modules/express.
OK, alors maintenant nous connaissons l'utilité du dossier .pnpm/
. .pnpm/
stocke tous les packages dans une structure de dossiers plats, de sorte que chaque package peut être trouvé dans un dossier nommé par ce modèle:
.pnpm/<name>@<version>/node_modules/<name>
On appelle ça le dossier du stockage virtuel.
Cette structure plate évite les problèmes de long chemin causés par les node_modules
créés par npm v2 mais maintient les packages isolés, contrairement aux node_modules
plats créés par npm v 3, 4, 5, 6 ou bien Yarn v1.
Regardons maintenant le réel emplacement d'express
:
▾ express
▸ lib
History.md
index.js
LICENSE
package.json
Readme.md
Est-ce une arnaque ? Il manque encore node_modules
! La deuxième astuce de la structure des node_modules
de pnpm est que les dépendances des packages se trouvent au même niveau de répertoire que l'emplacement réel du package dépendant. Donc les dépendances d'express
ne sont pas dans .pnpm/express@4.17.1/node_modules/express/node_modules/
mais dans .pnpm/express@4.17.1/node_modules/:
▾ node_modules
▾ .pnpm
▸ accepts@1.3.5
▸ array-flatten@1.1.1
...
▾ express@4.16.3
▾ node_modules
▸ accepts
▸ array-flatten
▸ body-parser
▸ content-disposition
...
▸ etag
▾ express
▸ lib
History.md
index.js
LICENSE
package.json
Readme.md
Toutes les dépendances d'express
sont des liens symboliques vers des dossiers appropriés dans node_modules/.pnpm/
. Placer les dépendances d'express
un niveau supérieur permet d'éviter les liens symboliques circulaires.
Donc, comme vous pouvez le voir, même si la structure node_modules
pnpm semble inhabituelle au premier abord:
- il est complètement compatible avec Node.js
- les packages sont bien regroupés avec leurs dépendances
La structure est un peu plus complexe pour les packages avec des dépendances paires mais l'idée est la même: utiliser des liens symboliques pour créer une imbrication avec une structure de dossier plate.