4

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

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

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

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

因此,假设我取决于A使用特定版本的B. 在 A 中package.json,我没有指定版本,但它包含在yarn.lock.

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

我知道我可以通过传入一个特定的版本来解决这个问题A/package.json(至少我认为)。

但是有没有一个选项可以告诉 yarn 查看yarn.lock依赖项?

4

1 回答 1

12

TLDR:

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


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

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

yarn.lock用来做什么的?

yarn.lock用于解决给version定. 它用于确定应将模块解析为什么。那根本不是它的用例semver versionpackage.jsonsemver version

正如yarn DOCS中提到的:为了在机器上获得一致的安装,Yarn 需要比您在包 json 中配置的依赖项更多的信息。Yarn 需要准确存储每个依赖项的安装版本

为此,Yarn 使用yarn.lock项目根目录中的文件。

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

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

由文件semver version决定 。package.jsonyarn.lock文件只是查找要 为给定编号安装哪个版本提交哈希。semver version

鉴于模块的 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 会在 lockfile 中寻找一个条目bluebird@^2.9.30。它存在,因此被解析为version=2.11.0
  2. 如果 package.json 有bluebird: "^2.9.0", yarn 会在 lockfile 中寻找一个条目bluebird@^2.9.0。它不存在。假设满足 semver 标准的最新稳定版本是2.13.0,然后 yarn 添加一个条目 for bluebird@^2.9.0,resolved to 2.13.0。在为给定的 bluebird 解析版本时,semver version在 lockfile 中 moduleA 的依赖项中为 bluebird 存在什么条目并不重要。

Semver Version不受yarn.lock文件中模块的依赖项映射中存在的条目的影响。

所以,如果 package.json 有bluebird: "", yarnbluebird@会在 lockfile 中寻找一个条目,但找不到它。因此,它解析bluebird: ""为最新版本,假设3.5.0. 现在,yarn 将为bluebird@resolve to添加一个条目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,您需要有一个B@in resolve to 的条目。一旦有 的条目,所有后续安装将始终获取的版本。yarn.lock1.0.0yarn.lockB@1.0.0B=""

以下是您需要采取的步骤来完成相同的操作:

方法 1(推荐)

如果您希望 B 解析为最新版本:

  1. 添加B:""A的package.json
  2. 运行yarn install。这将添加一个已B@解析到最新版本的条目。
  3. 推送yarn.lock文件。
  4. 现在就形成,无论谁运行,yarn install都会得到相同的版本。

方法二

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

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

这种方法非常危险,因为您可以轻松破坏某些东西。您的 yarn.lock 文件应始终由 yarn 管理

方法 3(推荐)

如果您希望 B 保持在 1.0.0

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

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

如果您查看此文档:,他们已经清楚地提到 yarn 将仅使用顶级yarn.lock 文件并忽略依赖项中存在的锁定文件。

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

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

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

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

于 2018-06-23T12:08:32.727 回答