纱线:使用 yarn.lock 的依赖项

Yarn: use yarn.lock of dependencies

我用yarn直接从公司的GitLab安装包:

yarn add git+ssh://<user>@<host>:<repo>

对于一级依赖,我使用yarn --pure-lockfile根据yarn.lock重构我的node_modules

然而,对于二级依赖项,yarn 似乎总是安装最新版本。

所以假设我依赖 A,它使用特定版本的 B 进行测试。在 A 的 package.json 中我没有指定版本,但它包含在 yarn.lock.

当我现在安装包 A 时,yarn 将获得最新版本的 B,尽管 A/yarn.lock

中有条目

我知道我可以通过在 A/package.json 中传递特定版本来解决这个问题(至少我认为是这样)。

但是是否有选项告诉 yarn 查看 yarn.lock 依赖项?

TLDR:

When you install dependencies in your application, only your own yarn.lock file is respected. Lockfiles within your dependencies will be ignored. Reference


让我们先把一些事情弄清楚:

  1. --pure-lockfile 与正常的纱线安装相同,只是它不会生成 yarn.lock 文件或更新文件(如果存在)。
  2. Yarn 默认情况下总是从 yarn.lock 读取以在安装时解决依赖关系,除非随 --no-lockfile 一起提供。所以,没有必要告诉它yarn.lock读取。

yarn.lock有什么用?

yarn.lock用于解析version应该取什么 给定 package.json 中模块的 semver version。它 而不是 用于确定 semver version 应该将模块解析为什么。那根本就不是它的use-case.

As mentioned in yarn DOCS: In order to get consistent installs across machines, Yarn needs more information than the dependencies you configure in your package json.. Yarn needs to store exactly which versions of each dependency were installed.

To do this Yarn uses a yarn.lock file in the root of your project.

所以,为了解决 semver version 的依赖关系,yarn 总是依赖于 package.json。对于给定的 semver version,yarn 检查 yarn.lock 文件以查看它应该获取什么 version。这就是纱线 Deterministic 的原因(npm 使用相同的技术,后者使用 npm-shrinkwrap.json)。

示例:像^1.2.4 这样的Semver 版本可以解析为任何版本号>= 1.2.3 and < 2.0.0。如果没有 yarn,npm 将在一台机器上安装 1.2.4,但在另一台机器上安装 1.9.9,具体取决于安装时出现的 latest 版本。这是yarn使用yarn.lock.

解决的问题

The semver version is determined by the package.json file. The yarn.lock file is only a lookup for which version and commit hash to install for the given semver version number.

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"
  1. 如果 package.json 有 bluebird: "^2.9.30",yarn 在锁定文件中查找条目 bluebird@^2.9.30。它存在,因此解析为 version=2.11.0.
  2. 如果 package.json 有 bluebird: "^2.9.0",yarn 在锁定文件中查找条目 bluebird@^2.9.0。它不存在。假设满足 semver 标准的最新稳定版本是 2.13.0,则 yarn 为 bluebird@^2.9.0 添加一个条目,解析为 2.13.0。在解析给定 semver version 蓝鸟的版本时,锁定文件中模块 A 的依赖项中的蓝鸟条目并不重要。

Semver Version is not affected by what entries are present in the dependencies map for a module in yarn.lock file.

因此,如果 package.json 有 bluebird: "",yarn 在锁定文件中查找条目 bluebird@ 但无法找到它。因此,它将 bluebird: "" 解析为最新版本,假设 3.5.0。现在,纱线将为 bluebird@ 添加一个条目 resolved to 3.5.0.

bluebird@:
  version "3.5.0"
  resolved "https://<...>/bluebird-3.5.0.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"

只要 yarn 遇到 {bluebird: ""},它就会在锁定文件中找到 bluebird@ 的条目,因此总是将其解析为 3.5.0

解决你的问题

要将 B: "" 解析为版本 1.0.0,您需要将 yarn.lock 中的 B@ 条目解析为 1.0.0。一旦 yarn.lockB@ 的条目,所有后续安装将始终获取 B="" 的版本 1.0.0

以下是您需要完成的步骤:

方法 1(推荐)

如果你想让B解析到最新版本:

  1. 在A的package.json中添加B:""
  2. 运行yarn install。这将为 B@ 添加一个条目,解析为最新版本。
  3. 推送 yarn.lock 文件。
  4. 表格现在开始,谁运行yarn install将获得相同的版本。

方法二

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

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

这种方法非常危险,因为您很容易破坏某些东西。您的 yarn.lock 文件应始终为 managed by yarn

方法 3(推荐)

如果你想让B保持在1.0.0

  1. 在 A 的 package.json 中将 B 的版本固定为 1.0.0
  2. 运行yarn install。这将在锁定文件中添加一个条目 B@1.0.0
  3. 推送yarn.lock文件
  4. 现在开始,谁运行 yarn install 将获得 B 的版本 1.0.0

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

如果你检查这个 doc:,他们已经明确提到 yarn 将使用 仅顶级 yarn.lock 文件并忽略存在的锁定文件在依赖项中。

目前无法使用其中存在的 yarn.lock 来锁定二级依赖项。我认为没有必要。事实上,纱线的创造者解释了 here 为什么会这样。原因是:

  1. 二级依赖需要安装的版本可以是 正如我所解释的,顶级 yarn.lock 文件很好地捕获了 以上。
  2. 当直接使用它们时,您将永远无法更新您自己的应用程序中的子依赖项的版本,因为它们会被其他人锁定yarn.lock 文件。 你可以通过我对 yarn 如何解决依赖关系的解释来验证这一点。
  3. Yarn 永远无法折叠(删除重复)依赖项,因此兼容的版本范围只能安装一个版本。

此外,如在您的用例中,如果 A 具有仅适用于版本 1.0.0 的依赖项 B,则 A 的 package.json 应该为 B 提到的版本为 1.0.0 并且不是 ””。您始终可以修复您的顶级 yarn.lock 以添加一个条目 B@ 解析为 1.0.0 但不建议手动修复 yarn.lock 文件,正如我上面提到的.

希望对您有所帮助!如有任何疑问,请在评论中联系我。