纱线--pnp是什么?

时间:2018-11-03 20:29:03

标签: yarnpkg

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

我想知道它到底能做什么?

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

谢谢。

2 个答案:

答案 0 :(得分:17)

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

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


没有即插即用

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

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

使用即插即用

使用PnP,工作流程如下:

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

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


¹正如您提到的,我们还在项目中生成一个.pnp文件夹。此文件夹旨在包含两种类型的数据:

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

  • 虚拟包,这是为依赖项树中列出对等依赖项的每个包创建的符号链接。无需赘述,它们是设计的必要部分,并且必须像以前一样使require.resolve起作用。


它如何工作?

.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进行要求调用时,必须从/cache/lodash-1.0.0加载所需的文件。在实践中,这有点复杂(我们保留了逆映射以提高性能,我们使用相对路径来确保可移植性,等等),但是这里有一个通用概念。


奖励回合:使用即插即用+拉链加载(纱2)

奖金::对于Yarn 2,我们将进一步改善此工作流程。它将是这样的:

  1. 我们从注册表中下载tarball,然后将其存储到缓存中(脱机镜像和缓存之间没有更多区别-它们相同)
  2. 我们生成与以前相同的.pnp.js文件

就是这样!如您所见,我们不再对软件包进行解压缩(相反,我们在运行时使用Node loader从软件包档案中读取它们)。

这样做有一个非常有趣的属性:如果同时存在缓存和.pnp.js文件,则无需运行yarn install即可使应用程序正常工作!为了确保拥有这些文件,您只需要将它们添加到存储库中,然后像对其他所有文件一样对它们进行版本控制即可。²

这非常有用,因为您无需记住在yarn installgit rebasegit pull之后运行git checkout,并且CI系统变得更快,更稳定因为他们不需要特殊的设置-只需克隆您的应用程序即可使用。


²在有人提到它之前-检入存储库中的二进制文件是perfectly finenode_modules之所以很难在存储库中检入,是因为文本文件数量成倍增加,这给Git带来了巨大压力-从技术上讲,从哲学上讲,由于无法进行代码审查

在我所描述的情况下,我们没有遇到相同的问题,因为文件数量受到限制(每个软件包一个文件一个),并且对其进行审核非常容易-实际上,在您可以清楚地看到PR向您的项目添加了多少个新软件包!

答案 1 :(得分:1)

它仅导入要使用的软件包的各个部分,从而使{肿的node_modules文件夹更加精简。

例如,考虑仅使用lo-5或ramda等相对较大的库,而仅使用其中的4-5个函数-仅获取实际使用的最小值就可以节省多少。

我相信它还不能100%完全稳定,但是仍然是保持雷达状态的不错选择:)