yarn --pnp 是什么意思?

What does yarn --pnp?

有一个名为 Plug'n'Play 的新 Yarn 功能。

我想知道它到底是做什么的?

我知道它正在创建一个 .pnp 文件夹和一个 .pnp.js 文件,但它是否会更改计算机上的其他任何内容,例如某处的配置文件?

谢谢。

它只导入您将要使用的包的部分,使臃肿的 node_modules 文件夹变得非常非常精简。

例如,当您仅使用 lodash 或 ramda 等相对较大的库时,请考虑其中的 4-5 个函数 - 如果仅使用实际使用的最小值,您可以节省多少。

我相信它还不是 100% 完全稳定,但仍然是一个值得关注的好选择:)

我设计并实现了 PnP,所以我可以谈论它几个小时

tl;dr: 我们只写 .pnp.js.pnp 文件夹(在常规 Yarn 缓存之上)。我们不会在其他任何地方存储配置。


没有即插即用

当您 运行 yarn install(即使没有 PnP)时,会发生一些事情:

  1. 如果您使用 offline mirror 功能,我们会从注册表下载压缩包并将它们存储在离线镜像文件夹中
  2. 无论您是否使用离线镜像,我们都会解压所有下载的压缩包并将其文件存储在 Yarn 缓存中
  3. 然后我们找出缓存中的哪些文件应该复制到 node_modules
  4. 中的哪个位置
  5. 我们应用计算的更改(基本上是一堆 rsync 操作)

即插即用

使用 PnP,工作流变成这样:

  1. 没有变化,我们从离线镜像中的注册表下载 tarball(如果启用)
  2. 没有变化,我们仍然将它们解压到 Yarn 缓存中
  3. 我们生成一个 .pnp.js 文件¹

就是这样。除了 .pnp.js 文件(和缓存,但它之前已经存在)之外没有其他生成的文件。


¹ 如您所述,我们还在项目中生成了一个 .pnp 文件夹(.yarn as of Yarn 2)。此文件夹旨在包含两种类型的数据:

  • Unplugged 包是必须是项目本地的包。通常,这些是带有安装后脚本的包(我们不能将它们存储到缓存中,因为生成的工件可能因项目而异)。

  • 虚拟包,它们是为列出对等依赖项的依赖关系树中的每个包创建的符号链接。不深入细节,它们是设计的必要部分,并且需要使 require.resolve 像以前一样工作。 从 Yarn 2 开始,这些文件不再存在


它是如何工作的?

.pnp.js 文件包含类似于以下内容的信息:

webpack@1.0.0 -> /cache/webpack-1.0.0/
              -> it depends on lodash@1.0.0

lodash@1.0.0  -> /cache/lodash-1.0.0/
              -> no dependencies

通过这些信息,解析可以正确推断当 /cache/webpack-1.0.0 中的文件对 lodash 进行 require 调用时,必须从 /cache/lodash-1.0.0 加载所需的文件。它在实践中有点复杂(我们保留了一个逆向映射来改进性能,我们使用相对路径来确保可移植性等),但通用概念就在那里。


奖励回合:即插即用+Zip 加载(Yarn 2)

奖励: 通过 Yarn 2,我们将进一步改进此工作流程。这就是它的样子:

  1. 我们从注册表下载 tarball,然后存储到缓存中(不再区分离线镜像和缓存 - 它们是相同的)
  2. 我们生成与之前相同的 .pnp.js 文件

就是这样!如您所见,我们不再解压包(相反,我们使用节点加载器在 运行 时间从包档案中读取它们)。

这样做有一个非常有趣的地方属性:如果你的缓存和.pnp.js文件都在那里,你就不需要运行 yarn install你的应用程序上班!并且为了确保您拥有这些文件,您只需将它们添加到您的存储库并像处理其他所有文件一样对其进行版本控制。²

这非常有用,因为您不需要记住 git rebasegit pullgit checkout 之后的 运行 yarn install,并且您的CI 系统变得更快、更稳定,因为它们不需要特殊设置 - 只需克隆您的应用程序,它就会正常工作。


² 在有人提到它之前 - 在存储库中签入二进制文件是 perfectly finenode_modules 之所以在你的存储库中签入是一件非常糟糕的事情,是因为文本文件的数量呈指数级增长,这给 Git 带来了巨大的压力——技术上,但在哲学上也是代码无法进行评论。

在我描述的情况下,我们不会遇到同样的问题,因为文件的数量是有限制的(每个包只有一个文件),审查它们非常容易——事实上,更好的是你可以清楚地看到有多少新包被一个 PR 添加到你的项目中!