96

如果我的包有这些依赖

{ "name": "my-package",
  "dependencies": { "foobar":"~1.0.3", "baz":"2.0.9" }

并且foobar包有这些依赖

{ "name": "foobar",
  "dependencies": { "baz":"^2.0.0" }

而最新发布的版本baz2.1.0,第一次运行yarn将安装baz@2.1.0foobar/node_modules.

我如何强制纱线使用baz@2.0.9包装foobar

我的理解是,这可以使用npm shrinkwrap(a la this question)。


我的问题的总结可能是:Yarn 创建了可重复的、确定性的安装,但我如何自定义该安装?

4

3 回答 3

134

如果您确实有一个子依赖项,它在接受哪些版本方面过于严格,您可以使用 yarn 覆盖它们。

更新编辑:从 1.0 开始,Yarn 现在正式支持“分辨率”块。因此,覆盖分辨率的方法是将这样的块添加到package.json

"resolutions": {
      "package-a": "2.0.0",
      "package-b": "5.0.0",
      "package-c": "1.5.2"
}

有时您会收到有关“不兼容”版本的警告,但我发现某些软件包(如 socket.io)在它们接受的版本方面过于严格,所以我很乐意选择最新版本,因为它实际上并没有破坏事物。

下面的原始但过时的答案。

听起来原来的问题并不完全正确,但原来的问题实际上是我想要回答的问题,我找到了答案,所以这里是为了后代:

我正在使用 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的文档中,我找到了对可以在 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 中添加一个新的“解决方案”块,实际上它在所有需要它的地方将组件发射器扁平化为 1.2.1,现在我的客户端代码中只有一个副本。

(现在resolutions完全支持该块yarn,所以你甚至不需要使用--flat。)

于 2016-12-11T03:43:02.343 回答
52

这现在可以通过 yarn 的选择性版本解析功能来实现。

在您的项目中package.json,使用resolutions

  "resolutions": {
    "foobar/**/baz": "2.0.9"
  }

这会覆盖 packagefoobar的(以及它下面的任何其他包)的版本baz,强制它是 2.0.9 版本。

于 2017-10-07T01:39:46.913 回答
1

编辑:现在已弃用,请改为阅读此答案:

https://stackoverflow.com/a/46615878/2398593


@SomeCallMeTime答案很棒,我们已经在工作中这样做了一个月。

不幸的是,自 v0.24.x 以来,这不再可能(请参阅该评论)。

Github上有一个打开的PR,其中包含一个 RFC 提案,可以通过一种简单的方式来处理该用例,而无需密切关注生成的锁定文件。

于 2017-05-23T07:08:02.963 回答