Yarn:使用依赖项的yarn.lock

5
我使用yarn从公司的GitLab直接安装软件包:
```yarn add git+ssh://@:```
对于第一级依赖,我使用 ```yarn --pure-lockfile``` 根据 ```yarn.lock``` 重构我的 ```node_modules``` 文件夹。
然而,对于第二级依赖,yarn似乎总是安装最新版本。
比如说,我依赖于 A,A用特定版本的 B 进行了测试。在 A 的 package.json 中我没有指定版本,但它包含在 yarn.lock 文件中。
当我现在安装软件包 A 时,yarn会获取最新版本的 B,尽管在 A/yarn.lock 中有该版本的记录。
我知道我可以通过在 A/package.json 中传递特定版本来解决这个问题(至少我认为如此)。
但是,有没有选项告诉yarn查看依赖项的 ```yarn.lock``` 呢?

我们有类似的东西。我们有一个构建工具,我们将其作为库分发。依赖项的数量(其中大多数是传递性的)非常庞大。 - EECOLOR
1个回答

13

简而言之:

当您在应用程序中安装依赖项时,只有您自己的 yarn.lock 文件会被尊重。依赖项中的锁定文件将被忽略。参考链接


首先,让我们澄清一些事情:
1. `--pure-lockfile` 和普通的 `yarn install` 是一样的,只是它不会生成 `yarn.lock` 文件,也不会更新已存在的文件。 2. Yarn 在安装时默认会从 `yarn.lock` 中读取以解析依赖关系,除非使用 `--no-lockfile` 参数。因此,没有必要告诉它从 `yarn.lock` 中读取。
那么,`yarn.lock` 的作用是什么呢?
`yarn.lock` 用于根据 `package.json` 中模块的 `semver version` 解析应该获取的版本。它并不用于确定模块应该解析到哪个 `semver version`。这简单来说并不是它的用途。
如在yarn文档中提到的:为了在不同的机器上获得一致的安装结果,Yarn需要比你在package.json中配置的依赖项更多的信息。Yarn需要存储每个依赖项的确切版本安装情况。
为了实现这一点,Yarn在项目的根目录中使用一个yarn.lock文件。
因此,为了解决依赖项的semver版本,yarn始终依赖于package.json。对于给定的semver版本,yarn会检查yarn.lock文件以确定应该获取哪个版本。这就是使yarn具有确定性的原因(npm也使用类似的技术,它使用npm-shrinkwrap.json文件)。

例子: Semver 版本如 ^1.2.4 可以解析为任何满足 >= 1.2.3 and < 2.0.0 的版本号。没有 yarn,npm 在一个机器上会安装 1.2.4,但在另一个机器上会安装 1.9.9,这取决于安装时的最新版本。这是 yarn 使用 yarn.lock 来解决的问题。

semver 版本 是由 package.json 文件确定的。而 yarn.lock 文件只是一个查找表,用于确定给定 semver 版本 号应安装哪个 版本提交哈希

yarn 如何根据 semver 版本解析模块的版本?

假设我们当前的 yarn.lock 文件如下所示:

bluebird@2.9.6:
  version "2.9.6"
  resolved "https://<...>/bluebird-2.9.6.tgz#1fc3a6b1685267dc121b5ec89b32ce069d81ab7d"

bluebird@^2.9.30:
  version "2.11.0"
  resolved "https://<...>/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
...
myModule@5.1.0:
  version "5.1.0"
  resolved "https://<...>/moduleA-5.1.0.tgz#ce97130858add59d616ee80675383b0c127290a0"
  dependencies:
    bluebird "^1.0.0"

如果 package.json 中有 bluebird: "^2.9.30",yarn 会在锁定文件中查找一个条目 bluebird@^2.9.30。它存在,因此被解析为 version=2.11.0
如果 package.json 中有 bluebird: "^2.9.0",yarn 会在锁定文件中查找一个条目 bluebird@^2.9.0。它不存在。假设满足 semver 标准的最新稳定版本是 2.13.0,那么 yarn 会添加一个条目 bluebird@^2.9.0,解析为 2.13.0。在解析 bluebird 的给定 semver 版本时,不管锁定文件中 moduleA 的依赖项中有什么条目,都不会受到影响。

Semver 版本 不受锁定文件中模块的依赖项映射的影响。

所以,如果 package.json 中有 bluebird: "",yarn 会在锁定文件中查找一个名为 bluebird@ 的条目,但是找不到。因此,它会将 bluebird: "" 解析为最新版本,假设是 3.5.0。现在,yarn 将添加一个条目 bluebird@,解析为 3.5.0
bluebird@:
  version "3.5.0"
  resolved "https://<...>/bluebird-3.5.0.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"

从现在开始,每当yarn遇到{bluebird: ""},它将在lockfile中找到bluebird@的条目,因此将始终将其解析为3.5.0解决方案 要将B: ""解析为版本1.0.0,您需要在yarn.lock中有一个解析为1.0.0B@的条目。一旦yarn.lock有了B@的条目,所有后续的安装都将始终获取B=""的版本1.0.0
以下是您需要采取的步骤: 方法1(推荐)
如果您希望B解析为最新版本:
  1. 在A的package.json文件中添加B:""
  2. 运行yarn install。这将添加一个解析为最新版本的B@的条目。
  3. 推送yarn.lock文件。
  4. 从现在开始,无论谁运行yarn install都将获得相同的版本。

方法2

如果你希望B有一个旧版本:(强烈不推荐

  1. 在 A 的 package.json 中添加 B: 1.0.0
  2. 运行 yarn install。这将在 lockfile 中添加一个条目 B@1.0.0
  3. 在 yarn.lock 中将 B@ 添加到 B@1.0.0 旁边。 B@, B@1.0.0: ...
  4. 在 A 的 package.json 中将 B 的版本更改为 ""
  5. 推送 yarn.lock 文件。
  6. 从现在开始,无论谁运行 yarn install,都会得到 B 的版本为 1.0.0

这种方法非常危险,因为很容易出错。你的 yarn.lock 文件应该始终由 yarn 管理。

方法 3(推荐)

如果你希望 B 保持在 1.0.0 版本

  1. 在 A 的 package.json 文件中将 B 的版本修复为 1.0.0
  2. 运行 yarn install。这将在 lockfile 中添加一个条目 B@1.0.0
  3. 推送 yarn.lock 文件。
  4. 从现在开始,无论谁运行 yarn install,都会得到 B 的版本为 1.0.0

编辑:使用依赖项中的 yarn.lock 文件

如果你查看这个 doc,他们明确提到 yarn 只会使用顶层的 yarn.lock 文件,并忽略依赖项中存在的锁文件。

目前没有办法使用依赖项中的 yarn.lock 文件锁定二级依赖项。我认为这并不需要。事实上,yarn 的创建者在 这里 解释了为什么这样做。原因如下:

  1. 如我之前所解释的那样,顶层的yarn.lock文件可以很好地捕捉到要安装的二级依赖的版本。
  2. 当直接使用子依赖项时,您将无法更新子依赖项的版本,因为它们将被其他yarn.lock文件锁定。您可以通过我对yarn如何解析依赖关系的解释来验证这一点。
  3. Yarn无法折叠(去重)依赖项,以便兼容的版本范围只安装一个版本。

此外,就像在您的用例中一样,如果A有一个只能与版本1.0.0一起使用的依赖项B,A的package.json应该将B的版本指定为1.0.0而不是“”。您可以始终修复顶层的yarn.lock,添加一个解析为1.0.0B@条目,但不建议手动修复yarn.lock文件,如我之前所提到的。


哎呀,不小心发送了...无论如何。我们在隔离环境中测试了A,这意味着它有一个yarn.lock文件,其中包含所有我们确定可以与之一起工作的传递依赖项。现在我们想要使用A及其锁定文件中指定的所有依赖项版本。 - EECOLOR
1
“我不认为有必要。”- 当你的一个传递依赖项违反Semver规则时,你就会看到这种需要。唯一(我所知道的)没有这种需要的语言是Elm,它有一个检查Semver的编译器。在我们的一个库中,我们有一个将近10,000行的锁定文件,即使机会非常小,也会发生故障。 - EECOLOR
我理解你的观点。但看一下这个链接:https://yarnpkg.com/blog/2016/11/24/lockfiles-for-all/ 根据 James Kyle 的说法,当你在应用程序中安装依赖项时,只会遵循你自己的 yarn.lock 文件。依赖项内部的锁定文件将被忽略。 - yeshashah
我在我的答案中添加了一个编辑以反映这些理解。希望这可以帮助到您。 - yeshashah
"如我上面所述,顶层的yarn.lock文件可以很好地捕获要安装的二级依赖项版本。是的,同时您说不应该手动编辑yarn.lock。因此,如果捕获了错误的二级依赖项版本,则没有“允许”的方法来修复它。" - Frans
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接