Passa al contenuto principale

La node_modules flat non è l'unico modo

· 3 minuti di lettura

I nuovi utenti di pnpm mi chiedono spesso della strana struttura di node_modules che crea pnpm. Perché non è piatta? Dove sono tutte le dipendenze secondarie?

Presumo che i lettori dell'articolo abbiano già familiarità con la cartella node_modules piatta creata da npm e Yarn. Se non capisci perché npm 3 ha dovuto iniziare a utilizzare node_modules flat nella v3, puoi trovare un po' di preistoria in Perché dovremmo usare pnpm?.

Perché allora node_modules di pnpm è insolito? Creiamo due cartelle ed eseguiamo npm add express in una di esse e pnpm add express nell'altra. Ecco la parte superiore di ciò che si ottiene in node_modules della prima cartella:

.bin
accepts
array-flatten
body-parser
bytes
content-disposition
cookie-signature
cookie
debug
depd
destroy
ee-first
encodeurl
escape-html
etag
express

Puoi vedere l'intera cartella qui.

E questo è ciò che ottieni in node_modules creato da pnpm:

.pnpm
.modules.yaml
express

Puoi controllarlo qui.

Allora, dove sono tutte le dipendenze? C'è solo una cartella in node_modules chiamata .pnpm e un collegamento simbolico chiamato express. Bene, abbiamo installato solo express, quindi questo è l'unico pacchetto a cui la tua applicazione deve avere accesso

Leggi di più sul perché la severità di pnpm è una buona cosa qui

Vediamo cosa c'è dentro express:

▾ node_modules
▸ .pnpm
▾ express
▸ lib
History.md
index.js
LICENSE
package.json
Readme.md
.modules.yaml

express non ha node_modules? Dove sono tutte le dipendenze di express?

Il trucco è che express è solo un collegamento simbolico. Quando Node.js risolve le dipendenze, utilizza le loro posizioni reali, quindi non conserva i collegamenti simbolici. Ma dov'è la vera posizione di express, si potrebbe chiedere?

Qui: node_modules/.pnpm/express@4.17.1/node_modules/express.

OK, ora conosciamo lo scopo della cartella .pnpm/. .pnpm/ memorizza tutti i pacchetti in una struttura di cartelle piatte, quindi ogni pacchetto può essere trovato in una cartella denominata con questo modello:

.pnpm/<name>@<version>/node_modules/<name>

La chiamiamo cartella dell'archivio virtuale.

Questa struttura piatta evita i problemi di percorso lunghi che sono stati causati dai node_modules annidati creati da npm v2 ma mantiene i pacchetti isolati a differenza dei node_modules piatti creati da npm v3,4,5,6 o yarn v1.

Ora diamo un'occhiata alla vera posizione di express:

  ▾ express
▸ lib
History.md
index.js
LICENSE
package.json
Readme.md

È una truffa? Manca ancora la cartella node_modules! Il secondo trucco della struttura node_modules di pnpm è che le dipendenze dei pacchetti sono sullo stesso livello di cartella su cui si trova la posizione reale del pacchetto dipendente. Quindi le dipendenze di express non sono in .pnpm/express@4.17.1/node_modules/express/node_modules/ ma in .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

Tutte le dipendenze di express sono collegamenti simbolici a cartelle appropriate in node_modules/.pnpm/. Posizionare le dipendenze di express un livello in alto permette di evitare i collegamenti simbolici circolari.

Quindi, come puoi vedere, anche se la struttura node_modules di pnpm sembra inizialmente inusuale:

  1. è completamente compatibile con Node.js
  2. i pacchetti sono ben raggruppati con le loro dipendenze

La struttura è un po' più complessa per i pacchetti con dipendenze peer ma l'idea è la stessa: usare collegamenti simbolici per creare un annidamento con una struttura di cartelle piatta.