首页 > 解决方案 > 纱线 --pnp 是什么?

问题描述

有一个新的闪亮 Yarn 功能,称为 Plug'n'Play。

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

我知道它正在创建一个.pnp文件夹和一个.pnp.js文件,但是它会改变机器上的其他任何东西,比如某个地方的配置文件吗?

谢谢你。

标签: yarnpkg

解决方案


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

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


没有即插即用

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

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

即插即用

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

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

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


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

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

  • 虚拟包,它们是为列出对等依赖项的依赖关系树中的每个包创建的符号链接。在不深入细节的情况下,它们是设计的必要部分,并且需要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对 进行 require 调用时lodash,必须从 加载所需的文件/cache/lodash-1.0.0。在实践中它有点复杂(我们保留一个逆映射以提高性能,我们使用相对路径来确保可移植性等),但一般概念就在那里。


奖金回合:即插即用 + Zip 加载(纱线 2)

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

  1. 我们从注册表下载压缩包然后存储到缓存中(离线镜像和缓存之间没有更多区别 - 它们是相同的)
  2. 我们生成.pnp.js和之前一样的文件

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

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

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


²在有人提到它之前 - 签入存储库中的二进制文件非常好。在您的存储库中签入是一件非常糟糕的事情的原因node_modules是文本文件的指数级数量,这给 Git 带来了巨大的压力——在技术上,但在哲学上,因为代码审查变得不可能。

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


推荐阅读