Yarn:使用 yarn.lock 的依赖

Posted

技术标签:

【中文标题】Yarn:使用 yarn.lock 的依赖【英文标题】:Yarn: use yarn.lock of dependencies 【发布时间】:2018-08-29 01:05:33 【问题描述】:

我使用 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 时,尽管A/yarn.lock 中有条目,但纱线将获得最新版本的B

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

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

【问题讨论】:

我们也有类似的事情。我们有一个构建工具,我们将其作为库分发。依赖项的数量(其中大部分是可传递的)是巨大的。 【参考方案1】:

TLDR:

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


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

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

yarn.lock 是做什么用的?

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

yarn DOCS 中所述:为了保持一致 跨机器安装,Yarn 需要的信息比 您在包 json 中配置的依赖项。纱线需要 store 确切地安装了每个依赖项的哪些版本

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

因此,为了解决依赖关系的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,这取决于安装时存在的 最新 版本。这是yarn使用yarn.lock解决的问题。

semver versionpackage.json 文件。 yarn.lock 文件只是一个查找 versioncommit hash 为给定的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"
    如果 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。在解析给定蓝鸟 semver version 的版本时,锁定文件中模块 A 的依赖项中的蓝鸟条目并不重要。

Semver Version不受条目的影响 存在于 yarn.lock 文件中的模块的依赖关系图中。

所以,如果 package.json 有 bluebird: "",yarn 会在 lockfile 中查找条目 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: "" 时,Form 现在会在锁定文件中找到 bluebird@ 的条目,因此将始终将其解析为 3.5.0

您的问题的解决方案

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

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

方法 1(推荐)

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

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

方法 2

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

    在A的package.json中添加B: 1.0.0。 运行yarn install。这将在锁定文件中添加一个条目B@1.0.0。 在 yarn.lock 中添加 B@B@1.0.0B@, B@1.0.0: ... 在 A 的 package.json 中将 B 的版本更改为 ""。 推送yarn.lock 文件。 现在打开表格,运行yarn install 的人将获得B 的版本为1.0.0

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

方法 3(推荐)

如果你想让 B 保持在 1.0.0

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

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

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

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

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

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

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

【讨论】:

首先感谢您非常好的回答。然而,这不是在现实世界中可用的解决方案。实际的问题是我们有一个库(A),我们可以在其中指定一个具有固定版本(1.0.0)的依赖项(B),但是 B 本身也有可能没有被锁定的依赖项。 糟糕,意外发送...无论如何。我们单独测试了 A,这意味着它有一个 yarn.lock 文件,其中包含我们确信它可以使用的所有传递依赖项。现在我们想将 A 与它的所有依赖项的版本一起使用,如其锁定文件中指定的那样。 “我认为没有必要。” - 一旦您的传递依赖项之一违反了 semver 规则,您就会看到需要。唯一不需要的语言(我知道的)是 Elm,它有一个检查 semver 的编译器。在我们的一个库中,我们有一个将近 10.000 行的锁定文件,即使几率很小,也会发生损坏。 我明白你的意思。但是看看这个:yarnpkg.com/blog/2016/11/24/lockfiles-for-all 根据 James Kyle 的说法,当您在应用程序中安装依赖项时,只有您自己的 yarn.lock 文件受到尊重。依赖项中的锁定文件将被忽略。 还在我的回答中添加了一个编辑以反映这些理解。希望这会有所帮助。

以上是关于Yarn:使用 yarn.lock 的依赖的主要内容,如果未能解决你的问题,请参考以下文章

Yarn:将 JavaScript 依赖项重新部署到生产服务器的过程(使用 `yarn.lock` 文件)

yarn.lock文件

如何解决 Yarn.lock 中开发依赖项的特定依赖项

yarn.lock文件

在 docker 容器内安装依赖项后如何复制回主机 package-lock.json/yarn.lock?

关于package.json package-lock.json 和 yarn.lock 的安装问题