如何使用`yarn`覆盖嵌套的依赖关系?


75

如果我的包裹有这些依赖

{ "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(la la this question)可以实现这一点


我的问题的摘要可能是:纱线创建可重复的确定性安装,但是如何自定义该安装?


1
你们有没有找到答案?
原子弹手

@atomman实际上,我认为这个问题的依据是错误的。Yarn已确定我的顶级软件包版本号与另一个依赖项的子依赖项之间存在不兼容。因此,它正确地决定给该依赖项该库自己的版本。
克里斯·

1
谢谢回答。尽管我不确定我是否同意,因为baz@2.0.9是否可以满足所有要求。尽管可以将它视为一种功能,但是yarn始终为子模块提供最新的依赖关系。但是,我确实认为yarn应该为这些情况提供一种依赖关系解决机制,但这就是另一个讨论。:)
atomman

@atomman哦,是的,我同意你(并同意我的问题的前提),但是我认为我实际上遇到的真正问题与我在问题中描述的问题有细微的差别。
克里斯·W

Answers:


108

如果实际上您确实对要接受的版本具有过分的限制,则可以使用yarn覆盖它们。

更新的编辑:从1.0开始,Yarn现在正式支持“ resolutions”块。因此,覆盖分辨率的方法是将这样的代码块添加到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选项,这将迫使纱线在整个项目中选择不超过每个卷装之一。在我看来,这似乎有些过激,因为我敢肯定,实际情况下,旧版本和新版本的软件包之间是不兼容的。我只是想从我的客户端代码中删除一个多余的软件包,以减小下载量。我仍然希望所有开发包都能正常工作

但是在有关--flat的文档中,我找到了可以在package.json中使用的“ resolutions”块的引用:

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

因此,我尝试"component-emitter" : "1.2.1"在package.json中放入一个新的“ resolutions”块,实际上对于需要它的所有位置,它都会将component-emitter展平为1.2.1,现在我的客户端代码中只有一个副本。

(现在该resolutions块已完全受支持yarn,因此您甚至不需要使用--flat。)


2
非常感谢您的回答。因此,我认为解决方案至少部分是“编辑yarn.lock文件”,这是我一开始担心的事情。但这是有道理的,纱线不会竭尽全力去破坏那个文件。
克里斯·W

毫不动摇地为我工作package.json。有async-busboydep并想更改其sub-dep-的版本busboy。因此,我只是替换busboy "0.2.13"busboy "mscdex/busboy#76c3d58",ranyarn install和voila,一切正常。奇怪的是,yarn不会更新锁定文件中的“ busboy”块,但是只要它起作用,就不会对我造成太大的困扰。
亚历克·梅夫

当然,只要您只使用纱线。npm install但是,如果其他人来运行,他们会得到错误的版本。我认为,如果同时修改这两种方法,它可能仍然可以工作,尽管不如使用yarn那样细粒度-并且如果要安装的内容是所添加的另一个程序包的依赖项,则“分辨率”至少应覆盖新的软件包相关性,这样您就不会最终获得同一软件包的多个版本。
SomeCallMeTim

不能长期有效地起作用。一旦yarn upgrade运行,该yarn.lock文件将被覆盖,而resolutions在你的部分package.json被嵌套依赖忽略。
Michael Plotke's

1
@MichaelPlotke现在,Yarn 1.0正式支持“分辨率”部分,因此我的答案再次起作用。:)
SomeCallMeTim

40

现在,可以使用纱线的选择性版本解析功能

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

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

这将覆盖包foobar(及其下的任何其他包)的版本baz,强制其为2.0.9版本。


1
不适用于工作空间:(请参阅上面的评论
。– Marecky

2

@SomeCallMeTime答案很好,我们已经在工作一个月了。

不幸的是,从v0.24.x开始这已经不可能了(请参阅该注释)。

Github上有一个开放的PR,其中包含RFC提案,以一种简单的方式来处理用例,而不必关注生成的锁文件。


从1.0开始,我的答案再次生效。查看更新的编辑。:)
SomeCallMeTim
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.