为了提高英语水平和保持技术成长,开始按计划翻译一些短篇和博客,有问题欢迎讨论👻
原文:Flat node_modules is not the only way
原作者:Zoltan Kochan
正文
pnpm的新用户经常问我关于pnpm创建后的node_module结构为什么这么奇怪。为什么不是扁平化的?所有的次级依赖在哪里?
我假设阅读这篇文章的读者都已经熟悉了npm和yarn创建后的扁平化
node_modules,如果你不明白npm在v3中开始使用扁平化node_modules,你可以在Why should we use pnpm?中找到一些历史说明
那么为什么pnpm的node_modules不寻常呢?我们来创建两个目录,一个运行npm add express,另一个运行pnpm add express,下面是你在第一个目录的node_modules中得到的顶部内容结构
.bin
accepts
array-flatten
body-parser
bytes
content-disposition
cookie-signature
cookie
debug
depd
destroy
ee-first
encodeurl
escape-html
etag
express
你可以在这里看到整个目录。
然后这是你在pnpm创建的node_modules中得到的目录:
.pnpm
.modules.yaml
express
你可以在这里查看.
那么,所有的依赖项都在哪里呢,在node_modules中只有一个叫做.pnpm的文件夹和一个叫做express的symlink。好吧,因为我们只安装了express,所以这是你的应用可以访问的唯一package
在此阅读更多关于pnpm的严格性为什么是一件好事情
让我们看看express的内部:
▾ node_modules
  ▸ .pnpm
  ▾ express
    ▸ lib
      History.md
      index.js
      LICENSE
      package.json
      Readme.md
  .modules.yaml
express没有node_modules?express的所有依赖项在哪里?
诀窍在于,express只是一个symlink,但Node.js解析依赖关系时,它会使用express的真实位置,所以依赖不会保留在符号连接上,但是你可能会问,express的真实位置在哪?
这里:node_modules/.pnpm/express@4.17.1/node_modules/express.
现在我们知道了.pnpm文件夹的用途。.pnpm在一个扁平的文件夹结构中存储所有的packages,所以每个package都可以在这个模式命名的文件夹中找到
.pnpm/<name>@<version>/node_modules/<name>
我们称它为虚拟存储目录
这种扁平结构避免了npm v2创建的嵌套node_modules造成的长路径问题,但是又与npm v3,4,5,6和yarn v1的扁平化结构不同,保持了packages的隔离
现在我们来研究一下express的真实位置:
▾ express
  ▸ lib
    History.md
    index.js
    LICENSE
    package.json
    Readme.md
这是错误的吗?它仍然缺少node_modules!pnpm的node_modules结构的第二个诀窍是,packages的依赖关系在同一级的目录上,而package依赖的真正位置在这个目录上。所以express的依赖不在.pnpm/express@4.17.1/node_modules/express/node_modules/,而是在.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
express的所有依赖都是指向node_modules/.pnpm内目录的symlinks。express的依赖放在上一级,可以避免循环symlinks
所以你可以看到,尽管pnpm的node_modules结构从开始时看起来不寻常:
- 完全兼容Node.js
 - packages和相关依赖被很好的组合在一起
 
对于同样依赖关系的packages来说结构要复杂一些,但是想法是一样的:使用symlinks创建一个有扁平目录结构的嵌套