如何使用 `yarn` 覆盖嵌套依赖项?
How do I override nested dependencies with `yarn`?
如果我的包有这些依赖项
{ "name": "my-package",
"dependencies": { "foobar":"~1.0.3", "baz":"2.0.9" }
并且 foobar
包具有这些依赖项
{ "name": "foobar",
"dependencies": { "baz":"^2.0.0" }
并且 baz
的最新发布版本是 2.1.0
,yarn
的第一个 运行 将在 foobar/node_modules
中安装 baz@2.1.0
.
如何强制 yarn 使用 foobar
的 baz@2.0.9
包?
我的理解是,使用 npm shrinkwrap
(la this question)是可能的。
我的问题的总结可能是:Yarn 创建可重复的、确定性的安装,但我如何自定义该安装?
如果您确实有一个子依赖项,该子依赖项在接受的版本方面受到过度限制,您可以使用 yarn 覆盖它们。
更新编辑: Yarn 现在,从 1.0 开始,officially supports "resolutions" 块。因此,覆盖分辨率的方法是将这样的块添加到 package.json
:
"resolutions": {
"package-a": "2.0.0",
"package-b": "5.0.0",
"package-c": "1.5.2"
}
你有时会收到 "incompatible" 版本的警告,但我发现有些软件包(如 socket.io)在它们的版本中 过度 限制接受,所以我很乐意 select 最新版本,因为它实际上并没有破坏东西。
下面是原始但已过时的答案。
原来的问题听起来不完全正确,但原来的问题是实际上是我想要回答的问题,我找到了答案,所以在这里为子孙后代:
我正在使用 socket.io 库,它有 component-emitter
作为依赖项。但它有一对它需要的版本。这是我更改任何内容之前 yarn.lock 文件的样子:
component-emitter@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3"
component-emitter@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.0.tgz#ccd113a86388d06482d03de3fc7df98526ba8efe"
所以它在我的客户端代码中包含了组件发射器的两个副本。我看了看,在 1.1.2 和 1.2.0(或当前的 1.2.1)之间似乎没有任何重大变化。我首先尝试更改 yarn.lock 文件:
component-emitter@1.2.1, component-emitter@^1.2.1, component-emitter@1.1.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
这行得通,但是该文件有关于它是自动生成的警告,这意味着我添加的每个更新或新包都会影响此更改。稍微搜索找到 yarn --flat
选项,这将强制 yarn 在整个项目中的每个包中选择不超过一个。这对我来说似乎有点矫枉过正,因为我确信确实存在新旧软件包之间不兼容的实际情况。我只是想从我的客户端代码中删除一个冗余包,以使下载更小;我仍然希望所有开发包都能 正常工作 。
但是在 yarn --flat 的文档中我找到了对 "resolutions" 块的引用,它可以进入 package.json:
"resolutions": {
"package-a": "2.0.0",
"package-b": "5.0.0",
"package-c": "1.5.2"
}
所以我尝试将 "component-emitter" : "1.2.1"
放入我的 package.json 中的一个新的 "resolutions" 块中,实际上它在所有需要它的地方将组件发射器扁平化为 1.2.1,现在我的客户端代码中只有一份。
(现在 yarn
完全支持 resolutions
块,所以你甚至不需要使用 --flat
。)
编辑:现在已弃用,请改为阅读此答案:
@SomeCallMeTime's 很棒,我们在工作中已经这样做了一个月。
不幸的是,自 v0.24.x(见 comment)以来,这不再可能了。
有一个开放的 PR on Github 有一个 RFC 提案,它有一个简单的方法来处理该用例,而不必关注生成的锁定文件。
yarn 的 selective version resolution feature 现在可以做到这一点。
在您项目的 package.json
中,使用 resolutions
:
"resolutions": {
"foobar/**/baz": "2.0.9"
}
这会覆盖包 foobar
(以及它下面的任何其他包)的 baz
版本,迫使它成为版本 2.0.9。
如果我的包有这些依赖项
{ "name": "my-package",
"dependencies": { "foobar":"~1.0.3", "baz":"2.0.9" }
并且 foobar
包具有这些依赖项
{ "name": "foobar",
"dependencies": { "baz":"^2.0.0" }
并且 baz
的最新发布版本是 2.1.0
,yarn
的第一个 运行 将在 foobar/node_modules
中安装 baz@2.1.0
.
如何强制 yarn 使用 foobar
的 baz@2.0.9
包?
我的理解是,使用 npm shrinkwrap
(la this question)是可能的。
我的问题的总结可能是:Yarn 创建可重复的、确定性的安装,但我如何自定义该安装?
如果您确实有一个子依赖项,该子依赖项在接受的版本方面受到过度限制,您可以使用 yarn 覆盖它们。
更新编辑: Yarn 现在,从 1.0 开始,officially supports "resolutions" 块。因此,覆盖分辨率的方法是将这样的块添加到 package.json
:
"resolutions": {
"package-a": "2.0.0",
"package-b": "5.0.0",
"package-c": "1.5.2"
}
你有时会收到 "incompatible" 版本的警告,但我发现有些软件包(如 socket.io)在它们的版本中 过度 限制接受,所以我很乐意 select 最新版本,因为它实际上并没有破坏东西。
下面是原始但已过时的答案。
原来的问题听起来不完全正确,但原来的问题是实际上是我想要回答的问题,我找到了答案,所以在这里为子孙后代:
我正在使用 socket.io 库,它有 component-emitter
作为依赖项。但它有一对它需要的版本。这是我更改任何内容之前 yarn.lock 文件的样子:
component-emitter@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3"
component-emitter@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.0.tgz#ccd113a86388d06482d03de3fc7df98526ba8efe"
所以它在我的客户端代码中包含了组件发射器的两个副本。我看了看,在 1.1.2 和 1.2.0(或当前的 1.2.1)之间似乎没有任何重大变化。我首先尝试更改 yarn.lock 文件:
component-emitter@1.2.1, component-emitter@^1.2.1, component-emitter@1.1.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
这行得通,但是该文件有关于它是自动生成的警告,这意味着我添加的每个更新或新包都会影响此更改。稍微搜索找到 yarn --flat
选项,这将强制 yarn 在整个项目中的每个包中选择不超过一个。这对我来说似乎有点矫枉过正,因为我确信确实存在新旧软件包之间不兼容的实际情况。我只是想从我的客户端代码中删除一个冗余包,以使下载更小;我仍然希望所有开发包都能 正常工作 。
但是在 yarn --flat 的文档中我找到了对 "resolutions" 块的引用,它可以进入 package.json:
"resolutions": {
"package-a": "2.0.0",
"package-b": "5.0.0",
"package-c": "1.5.2"
}
所以我尝试将 "component-emitter" : "1.2.1"
放入我的 package.json 中的一个新的 "resolutions" 块中,实际上它在所有需要它的地方将组件发射器扁平化为 1.2.1,现在我的客户端代码中只有一份。
(现在 yarn
完全支持 resolutions
块,所以你甚至不需要使用 --flat
。)
编辑:现在已弃用,请改为阅读此答案:
@SomeCallMeTime's
不幸的是,自 v0.24.x(见 comment)以来,这不再可能了。
有一个开放的 PR on Github 有一个 RFC 提案,它有一个简单的方法来处理该用例,而不必关注生成的锁定文件。
yarn 的 selective version resolution feature 现在可以做到这一点。
在您项目的 package.json
中,使用 resolutions
:
"resolutions": {
"foobar/**/baz": "2.0.9"
}
这会覆盖包 foobar
(以及它下面的任何其他包)的 baz
版本,迫使它成为版本 2.0.9。