跳至主要内容

深入了解:Yarn PnP

信息

这些步骤完全是可选的

虽然我们建议对新项目使用 Yarn Plug'n'Play,但在现有项目中启用它可能需要时间投入。如果您愿意,可以跳过此部分,并在有更多时间和/或从中获得具体好处时再回来。

呼叫医生

Plug'n'Play 严格执行 依赖项规则。如果应用程序中的某些内容依赖于未列出的依赖项,您将收到错误,这可能会导致应用程序变得不稳定。

为了快速检测哪些地方可能依赖于不安全的模式,Yarn 提供了一个名为 Doctor 的工具。只需在项目中运行 yarn dlx @yarnpkg/doctor,Doctor 就会开始查看您的源文件,以检测任何可能存在问题的模式。

示例

例如,以下是 Doctor 过去对 webpack-dev-server 的评价

➤ YN0000: Found 1 package(s) to process
➤ YN0000: For a grand total of 236 file(s) to validate

➤ YN0000: ┌ /webpack-dev-server/package.json
➤ YN0000: │ /webpack-dev-server/test/testSequencer.js:5:19: Undeclared dependency on @jest/test-sequencer
➤ YN0000: │ /webpack-dev-server/client-src/default/webpack.config.js:12:14: Webpack configs from non-private packages should avoid referencing loaders without require.resolve
➤ YN0000: │ /webpack-dev-server/test/server/contentBase-option.test.js:68:8: Strings should avoid referencing the node_modules directory (prefer require.resolve)
➤ YN0000: └ Completed in 5.12s

➤ YN0000: Failed with errors in 5.12s

我们可以看到,Doctor 发现了一些合法问题

  • testSequencer.js 依赖于 @jest/test-sequencer,但未将其列为适当的依赖项 - 这将在 Yarn Plug'n'Play 下在运行时报告为错误,因为没有任何保证 @jest/test-sequencer 的版本将与该软件包经过测试的版本匹配。

  • webpack.config.js 引用了一个加载器,但未通过 require.resolve 传递其名称 - 这是不安全的,因为这意味着将相对于 webpack 软件包而不是 webpack-dev-server 的依赖项解析加载器。

  • contentBase-option.test.js 检查 node_modules 文件夹的内容 - 该文件夹在 Plug'n'Play 下将不再存在。

启用 Yarn PnP

  1. 查看 .yarnrc.yml 文件中的 nodeLinker 设置。
  2. 如果您找不到它,或者如果将其设置为 pnp,那么一切都很好:您已经在使用 Yarn Plug'n'Play!
  3. 否则,请从配置文件中将其删除并运行 yarn install.
  4. 提交更改。

寻找什么

现在您应该有一个可用的 Yarn Plug'n'Play 设置,但您的存储库可能仍需要一些额外的维护。一些需要记住的事情

  • 没有 node_modules 文件夹。请改用 require.resolve
  • 没有 .bin 文件夹。如果您依赖它们,请使用 yarn run bin 代替。
  • yarn node 替换不在 scripts 字段中的任何对 node 的调用。
  • 现在需要手动调用自定义预钩子(例如 prestart)(yarn prestart).

以下部分记录了所有这些内容及更多内容。一般来说,我们建议您在此处尝试运行应用程序并查看中断情况,然后在此处查看有关如何更正安装的提示。

编辑器支持

提示

我们在此仅介绍 VSCode,但我们有一个专门的文档页面,涵盖更多 IDE!

警告

确保项目顶级(而不是任意工作区)中列出了 IDE 扩展通常使用的所有依赖项,如 typescripteslintprettier 等。

  1. 安装ZipFS VSCode 扩展。
  2. 运行 yarn dlx @yarnpkg/sdks vscode并提交更改。
  3. 对于 TypeScript,不要忘记在 VSCode 中选择使用工作区版本

一般建议

使用 packageExtensions修复依赖项

软件包有时会忘记列出其依赖项。过去,这常常导致许多细微的问题,因此 Yarn 现在默认阻止此类不健全的访问。不过,只要您能够以安全和可预测的方式进行操作,我们就不希望它妨碍您完成工作,因此我们提出了 packageExtensions 设置。

例如,如果 react 忘记列出对 prop-types 的依赖项,您可以这样修复它

packageExtensions:
"react@*":
dependencies:
prop-types: "*"

如果 Babel 插件缺少对 @babel/core 的对等依赖项,则可以使用以下命令修复它

packageExtensions:
"@babel/plugin-something@*":
peerDependencies:
"@babel/core": "*"

您应该使用依赖项还是对等依赖项?这取决于上下文;根据经验,如果软件包是单例(例如 reactreact-redux,它也依赖于 React 上下文),您需要将其设为对等依赖项。在其他情况下,如果软件包只是一组实用程序,则使用常规依赖项即可(例如 tsliblodash 等)。

使用 yarn run bin 而不是 node_modules/.bin 调用二进制文件

node_modules/.bin 文件夹是一个实现细节,PnP 安装根本不会生成它。与其依赖它的存在,不如直接使用 yarn run bin 命令,该命令可以同时启动脚本和二进制文件

yarn run jest
# or, using the shortcut:
yarn jest

通过 yarn node 而不是 node 调用脚本

现在我们需要将一些变量注入到环境中,以便 Node 能够找到您的依赖项。为了实现这一点,我们要求您使用 yarn node,它会透明地执行繁重的工作。

注意:此部分仅适用于shell CLI。在您的 脚本 中定义的命令不受影响,因为我们确保 node 始终指向正确的位置,并已设置正确的变量。

为 PnP 支持设置您的 IDE

由于 Yarn Plug'n'Play 不会生成 node_modules 文件夹,因此某些 IDE 集成可能无法开箱即用。查看我们的 指南,了解如何修复它们。

查看我们的端到端测试

我们现在每天针对各种流行的 JavaScript 工具运行 端到端测试,以确保我们永不退步 - 或在第三方项目交付不兼容的更改时收到通知。

查看这些测试的源代码是检查使用特定工具链时是否必须设置某些特殊配置值的好方法。

故障排除

无法找到模块 [...]

此错误不是来自 Yarn:它是由 Node.js 解析管道发出的,告诉您磁盘上找不到包。

如果您已启用 Plug'n'Play,则 Node.js 解析管道应该将解析请求转发到 Yarn - 这意味着如果您收到此消息,则表示此转发未发生,您的第一个操作应该是找出原因。

通常,这是因为你使用 node ./my-script 而不是 yarn node ./my-script 调用了 Node.js 脚本。

一个软件包正尝试访问 [...]

虽然很少见,但有些软件包不会列出它们的所有依赖项。现在我们强制执行依赖项树各个分支之间的边界,这种问题比以前更加明显(尽管它一直存在问题)。

长期的修复方法是提交一个上游拉取请求,将缺少的依赖项添加到软件包列表中。鉴于有时可能需要一段时间才能合并它们,我们还提供了更短期的修复方法:在你的项目中创建 .yarnrc.yml,然后使用 packageExtensions 设置 将缺少的依赖项添加到相关软件包中。运行 yarn install 来应用你的更改,瞧!

如果你选择在上游存储库中打开 PR,你还可以将你的软件包扩展贡献给我们的 plugin-compat 数据库,帮助整个生态系统向前发展。