Novos usuários do pnpm frequentemente me perguntam acerca da estranha estrutura do node_modules
que o pnpm cria. Por que não é plano? Onde estão todas as sub-dependências?
Vou assumir que os leitores do artigo já estão familiarizados com o
node_modules
plano criado pelo npm e Yarn. Se você não entende por que o npm 3 teve que começar a usarnode_modules
planos na v3, você pode encontrar um pouco da história em Por que devemos usar o pnpm?.
Então, por que o node_modules
do pnpm é incomum? Vamos criar dois diretórios e executar npm add express
em um deles e pnpm add express
no outro. Aqui está o início do node_modules
do primeiro diretório:
.bin
accepts
array-flatten
body-parser
bytes
content-disposition
cookie-signature
cookie
debug
depd
destroy
ee-first
encodeurl
escape-html
etag
express
Você pode ver todo o diretório aqui.
E é isso que você obtém no node_modules
criado pelo pnpm:
.pnpm
.modules.yaml
express
Você pode conferir aqui.
Então, onde estão todas as dependências? Existe apenas uma pasta em node_modules
chamada .pnpm
e um link simbólico chamado express
. Bem, instalamos apenas express
, então esse é o único pacote que sua aplicação tem que ter acesso
Leia mais sobre porque o rigor do pnpm é uma coisa boa aqui
Vamos ver o que está dentro de express
:
▾ node_modules
▸ .pnpm
▾ express
▸ lib
History.md
index.js
LICENSE
package.json
Readme.md
.modules.yaml
express
não tem node_modules
? Onde estão todas as dependências de express
?
O truque é que express
é apenas um link simbólico. Quando o Node.js resolve dependências, ele usa suas localizações reais, portanto, não preserva links simbólicos. Mas onde está a localização real de express
, você pode perguntar?
Aqui: node_modules/.pnpm/express@4.17.1/node_modules/express.
OK, agora sabemos o propósito da pasta .pnpm/
. .pnpm/
armazena todos os pacotes em uma estrutura de pastas simples, então cada pacote pode ser encontrado em uma pasta nomeada por este padrão:
.pnpm/<name>@<version>/node_modules/<name>
Nós o chamamos de virtual store directory.
Essa estrutura plana evita os problemas de longos diretórios causados pelo node_modules
aninhados criado pelo npm v2, mas mantém os pacotes isolados ao contrário dos node_modules
criados pelo npm v3,4,5,6 ou Yarn v1.
Agora vamos olhar para a localização real de express
:
▾ express
▸ lib
History.md
index.js
LICENSE
package.json
Readme.md
É uma farsa? Ainda falta node_modules
! O segundo truque da estrutura node_modules
do pnpm é que as dependências dos pacotes estão no mesmo nível de diretório em que a localização real da dependência. Portanto, as dependências de express
não estão em .pnpm/express@4.17.1/node_modules/express/node_modules/
mas em .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
Todas as dependências de express
são links simbólicos para diretórios apropriados em node_modules/.pnpm/
. Colocar dependências de express
um nível acima permite evitar links simbólicos circulares.
Então, como você pode ver, mesmo que o node_modules
do pnpm pareça incomum no início:
- é totalmente compatível com Node.js
- os pacotes são bem agrupados com suas dependências
A estrutura é um pouco mais complexa para pacotes com dependências peer, mas a ideia é a mesma: usar links simbólicos para criar um aninhamento com uma estrutura de diretório simples.