【译】Symlinked `node_modules` structure

原文链接:https://pnpm.io/symlinked-node-modules-structure

node_modules 的符号链接结构

这篇文章仅仅描述没有 peer dependencies 的 pnpm, 是怎么构建 node_modules 结构的。

pnpm 的 node_modules 布局使用符号链接来生成一个嵌套的依赖结构。

在项目的 node_modules/.pnpm 里,每一个包都指向一个硬链接,指向内容寻址的仓库。让我们看看,假设你安装了 foo@1.0.0,它依赖 bar@1.0.0。pnpm 将会硬链接这两个包到 <store>下, 像下面这样:

node_modules
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    │           ├── index.js
    │           └── package.json
    └── foo@1.0.0
        └── node_modules
            └── foo -> <store>/foo
                ├── index.js
                └── package.json

现在 node_modules 下面还只有“真实”文件。一旦所有的包被硬链接到 node_modules,符号链接将会被创建以构建嵌套的依赖结构图。

你可能已经注意到,两个包都被硬链接进 node_modules 文件里的一个子文件。(foo@1.0.0/node_modules/foo)。之所以这么做是因为:

  1. 允许包导入他们自己。foo 应该能 require('foo/package.json')import * as package from "foo/package.json"

  2. 避免循环符号链接。 一个包的依赖被放置到和这个包相同层级的目录中。对于 Node.js 而言这两者并没有什么不同:依赖是在这个包的 node_modules 里面还是在这个包的上层目录下的 node_modules 里面。(由此知道,为什么 npm 和 yarn 要将包全部提升到 node_modules 下同一层级)

安装的下一步是用符号链接依赖。bar 将会被链接到 foo@1.0.0/node_modules 目录下:

node_modules
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    └── foo@1.0.0
        └── node_modules
            ├── foo -> <store>/foo
            └── bar -> ../../bar@1.0.0/node_modules/bar

下一步,直接依赖将会被处理。foo 将被符号链接进根 node_modules 目录,因为 foo 是这个项目的依赖。

node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    └── foo@1.0.0
        └── node_modules
            ├── foo -> <store>/foo
            └── bar -> ../../bar@1.0.0/node_modules/bar

这是一个非常简单的例子。然而,不管有多少的依赖和多深的依赖图,布局都将保持这个结构。

我们再添加 qar@2.0.0 作为 foo 和 bar 的依赖。新结构将会这样:

node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       ├── bar -> <store>/bar
    │       └── qar -> ../../qar@2.0.0/node_modules/qar
    ├── foo@1.0.0
    │   └── node_modules
    │       ├── foo -> <store>/foo
    │       ├── bar -> ../../bar@1.0.0/node_modules/bar
    │       └── qar -> ../../qar@2.0.0/node_modules/qar
    └── qar@2.0.0
        └── node_modules
            └── qar -> <store>/qar

正如你所见到的,即使现在依赖图更深了(foo 依赖 bar,bar 又依赖 qar),文件系统的目录深度依旧是相同的。

这个布局第一次看起来可能有点奇怪,但它完全兼容 Node 的处理模块算法。

当处理模块时,Node 会忽略符号链接,所以当 bar 从 foo@1.0.0/node_modules/foo/index.js 文件被引入 required 时,Node 不会使用 foo@1.0.0/node_modules/bar (它是个符号链接),相反,bar 会被解析到它的真实位置(bar@1.0.0/node_modules/bar)。

因此,bar 也能够解析在 bar@1.0.0/node_modules 下的依赖。

这个布局的最大好处是,仅是真实在项目的依赖里的包才能够被获取。而一个扁平化的 node_modules 结构,所有被提升的包都可以被获取到。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值