Yarn: 将 `--pure-lockfile` 设为 `install` 的默认值

创建于 2016-10-10  ·  54评论  ·  资料来源: yarnpkg/yarn

您是要请求一个 _feature_ 还是报告一个 _bug_?

_特征_

目前的行为是什么?

没有为install命令传递--pure-lockfile让我感到困惑,因为它在安装 node_modules 时修改了锁定文件。
我们在语义上达成一致, add/upgrade/remove是改变依赖关系,而install是一致地从锁文件重建 node_modules。

根据环境(当前安装的纱线版本)修改锁文件时,一致性会丢失。

什么是预期行为?

yarn install时不要写 yarn.lock 或 package.json 。
要更新 yarn.lock 使用yarn upgrade

请提及您的 node.js、yarn 和操作系统版本。

纱线 0.14

cat-feature needs-discussion

最有用的评论

这里发生了很多不同的事情,我想尝试解开(没有双关语)。

首先,人们提出了许多不同的要求,我认为这些要求是没有争议的(并且这些要求会使一些现有的行为成为错误,我很快就会谈到)。

来自原始错误报告。

根据环境(当前安装的纱线版本)修改锁文件时,一致性会丢失。
什么是预期行为?
安装 yarn 时不要写 yarn.lock 或 package.json。
要更新 yarn.lock 使用 yarn upgrade

更准确地说,在我看来,预期的语义是:

  • 如果package.json自上次yarn.lock更改后没有更改,则yarn.lock是事实来源,不应更新。
  • 如果package.json自上次以来发生了变化, yarn.lock发生了变化,则更新yarn.lock使其满足package.json并更新node_modules
  • 如果yarn update运行,重新解析所有依赖项并获取满足package.json的所有内容的最新版本。

这意味着当一个仓库第一次被克隆到一台机器上时,如果yarn.lock被签入,yarn 应该总是把它当作真实的来源,而不是对yarn.lock生成更新,然后跳转直接进入获取步骤。

在某种程度上,这不是纱线的当前行为,我认为这将是一个错误。


@esphen写道:

我同意。 应该首先讨论为什么 yarn install 默认写一个锁文件,因为它似乎与整个锁文件的概念不一致。 如果默认情况下不锁定版本,为什么要使用锁定文件?

我认为这是想说的是,如果现有的锁文件仍然是最新的,则纱线不应该写出新的锁文件。 我同意这一点。

我同意@bestander的观点,即默认情况下只有变异操作才应更新

这里的主要问题是对package.json的更改是否应该导致yarn.lock更新。 在我看来,如果到了改变package.json没有被满足yarn.lock ,就必须更新yarn.lock

锁定文件系统(如yarn)的一个重要不变式是,使用正常工作流程,开发人员可以确保在运行应用程序时实际使用的包与package.json指定的版本相匹配。 如果允许package.jsonyarn.lock不同步,这将是不正确的,唯一知道这一点的方法是让人类读者仔细阅读yarn.lock

大多数用户考虑锁文件的最佳方式是它是正在运行的纱线的工件,它代表当前package.json使用的所有包的精确版本。 通过签入,其他协作者、CI 和生产代码可以确保使用相同的版本。


@Guuz说:

因此,为了检查我是否正确理解这一点:
yarn 安装所有依赖项并修改锁文件。 在 CI 服务器上,您应该使用 yarn install --pure-lockfile?

这个问题呼应了一些人在这个线程中的观点。

Cargo 有一个--locked标志,表示“如果package.json不满足yarn.lock ,这是一个硬错误”。 Bundler 有一个类似的标志( --frozen ),它是在 Heroku 采用 Bundler 时添加的,如果人们对Gemfile进行本地更改并忘记检查Gemfile.lock

这个想法是,在您的正常开发过程中,您希望能够对package.json进行更改并让纱线确保yarn.lock保持同步(再次确保指定的版本在package.json始终匹配实际使用的内容)。

但是在部署时,发散实际上总是一个错误,因为这意味着您对package.json进行了更改,运行了本地yarn命令,而忘记签入yarn.lock . 这意味着package.json中的版本与应用程序运行时使用的实际版本不匹配,我们说这违反了 yarn 的基本不变量。


@esphen说:

在我看来,包管理器扮演的角色之一是尽可能轻松地开始项目开发。 一个简单的 yarn 安装应该可以获得您开始开发所需的所有包,而不会涉及任何混淆。

我认为这是没有争议的。

使用 npm 我有很多开发人员加入一个项目的实例,却发现一个项目在他们的机器上不起作用。 这些实例的发生是由于瞬态依赖性将版本碰撞到具有破坏性更改的版本或根本不遵循 semver。 我曾希望 yarn 能够解决这些问题,但如果项目的所有开发人员都应该运行 yarn install --pure-lockfile 以 100% 确定该项目将被构建,那么情况并非如此。

运行yarn install --pure-lockfile将意味着即使锁文件中的版本与package.json指定的版本冲突,也会遵守锁文件。 如果开发人员在更改package.json后忘记签入他们的yarn.lock ,那么这应该首先出现。

包管理器的另一个角色是让项目控制它们的依赖项。 如果默认情况下是纯的,开发人员可以查看过时的纱线以查看过时的版本,然后查看更改说明,避免任何破坏性更改。 这将使开发人员可以完全控制在给定的发布时间范围内只修改版本,而不是禁止开发人员执行 git commit -a 以避免意外的锁文件提交。

如果package.json没有改变,在我看来,如果yarn.lock得到更新,这是一个错误。 至少一个错误案例似乎在原始报告中:

根据环境(当前安装的纱线版本)修改锁文件。

我认为这是一个错误,应该纠正。

稍后在线程中, @thejameskyle说:

想象一个 memoize 函数,其中输入是 package.json,输出是 yarn.lock。

在我看来,这正是正确的心理模型(“当且仅当package.json更改时, yarn.lock才能更改”),如果抽象泄漏,我们应该修复它。


@adamchainz说:

关于以上的更多信息:我们的构建有来自 Github 的 coffeescript 作为子依赖。 coffeescript 推送了一些提交,我们在构建过程中通过运行 yarn install 得到了一个修改过的 yarn.lock

然后:

但是如果从 github 安装依赖项,它确实有不好的行为,正如我上面报道的

这里的问题是,yarn 没有将 git sha 视为 git 依赖项的锁定版本的一部分。 Cargo 和 Bundler 都有序列化到锁文件的“精确”版本的概念; 对于 git 源,“精确”版本是 SHA。 然后,当您仅使用package.jsonyarn.lock制作一个新的克隆并运行yarn ,获取您需要的代码所需的所有信息都在那里。

我必须承认,我在查看原始 git 代码时错过了这种交互; 代码中有一些 SHA 跟踪,但yarn install并不能确保水合依赖图尊重它。


TL; 博士

我同意@thejameskyle@kittens 的观点yarn.lock应该自动与package.json保持同步,因为我相信用户应该能够假设他们的package.json指定的版本与执行他们的应用程序时使用的内容对齐。

然而,即使package.json没有改变,似乎也有一些错误会导致yarn.lock中的不当流失:

  • 跨机器更改纱线版本更新锁文件
  • 即使package.json尚未更新,git 依赖项也会更新,然后更新锁文件

我们还应该考虑 Cargo 的--locked标志,如果开发人员更新package.json并且忘记签入更新的yarn.lock ,您可以在 CI 中使用它来快速失败构建

所有54条评论

我同意。 应该首先讨论为什么yarn install默认写入锁文件,因为它似乎与整个锁文件的概念不一致。 如果默认情况下不锁定版本,为什么要使用锁定文件?

如果不存在锁文件,则yarn install创建一个锁文件,即当有人将项目转换为使用yarn ,但始终编写它的理由尚不清楚。 我同意@bestander的观点,即默认情况下只有变异操作应该更新锁文件,即add/upgrade/remove

在升级 Yarn 并且它使用新的锁文件版本的情况下,是否应该有一种方法可以在没有add/remove/upgrade的情况下修改锁文件?

我想这个选项可以颠倒

yarn install --save-lockfile

2016年10月在18:53 17日,詹姆斯井[email protected]写道:

是否应该有一种方法可以在不添加/删除/升级的情况下修改锁定文件
例如:在升级 Yarn 并使用新锁文件的场景中
版本?


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/yarnpkg/yarn/issues/570#issuecomment -254282256,或者静音
线程
https://github.com/notifications/unsubscribe-auth/ACBdWJLpdvqiwcBwqE4KB3x3f4oCn_nVks5q07YYgaJpZM4KSlSw
.

我也对此感到困惑。 当前默认行为的原因是什么?

Afaik,默认行为没有充分的理由。
我想,这个想法是让人们的锁文件保持“常青”。

顺便说一句,欢迎公关

我认为它的原因是纱线最初是用单个install命令设计的,该命令被拆分为install/add/upgrade

因此,为了检查我是否正确理解这一点:

yarn安装所有依赖项并修改锁文件。 在 CI 服务器上,您应该使用yarn install --pure-lockfile吗?
为什么在安装过程中会修改锁定文件? 既然你没有升级任何东西...... Yarn 应该只安装锁文件中描述的包,对吧?

感谢您的解释!

问题是,如果锁文件默认是纯的,那么人们会忘记更新它,因为它是一个单独的命令。

@kittens不应该只在添加/删除/升级任何包时更新锁定文件吗? 那些应该总是升级锁定文件,以及初始安装。

问题是,如果锁文件默认是纯的,那么人们会忘记更新它,因为它是一个单独的命令

这是一个问题取决于您认为包管理器的主要目标是什么。

在我看来,包管理器扮演的角色之一是尽可能轻松地开始项目开发。 一个简单的yarn install应该可以获得您开始开发所需的所有包,而不会涉及任何混淆。

使用npm我有很多开发人员加入一个项目的实例,却发现一个项目在他们的机器上不起作用。 这些实例的发生是由于瞬态依赖性将版本碰撞到具有破坏性更改的版本或根本不遵循 semver。 我曾希望yarn会解决这些问题,但如果外卖是项目的所有开发人员都应该运行yarn install --pure-lockfile以 100% 确定该项目将要构建,那么这不是案子。

包管理器的另一个角色是让项目控制它们的依赖项。 如果默认情况下是纯的,开发人员可以查看yarn outdated以查看过时的版本,然后查看更改说明,避免任何破坏性更改。 这将使开发人员完全控制在给定的发布时间范围内仅更新版本,而不是禁止开发人员执行git commit -a以避免意外的锁文件提交。

我同意@esphen所说的一切。 我很惊讶纯行为并不是 Yarn 的默认设置——我认为这种一致性是 Yarn 相对于 NPM 的主要优势。 这应该是我认为从 NPM 切换的最令人信服的原因。

在我们开始使用yarn几天后,我们打破了构建,这让我们感到非常惊讶。 我真的认为--pure-lockfile是阅读了大部分文档后的默认行为,以及它如何比使用收缩包装的 npm 更好。 请默认:)

@ide想象一个场景,有人只是使用 npm 并更新package.jsonyarn.lock将如何更新?

有人可以写出导致锁文件被意外修改的场景吗? 这种变化是一个严重的变化,并且确实使锁文件成为二等公民,因为它要求对其进行显式更新,这意味着在记住哪些操作导致它被更新等方面需要大量开销。

关于以上的更多信息:我们的构建有来自 Github 的 coffeescript 作为子依赖。 coffeescript 推送了一些提交,我们在构建过程中通过运行yarn install得到了修改后的yarn.lock yarn install

diff --git a/foo/yarn.lock b/foo/yarn.lock
index ec667fa..bb1f6ae 100644
--- a/foo/yarn.lock
+++ b/foo/yarn.lock
@@ -930,9 +930,9 @@ code-point-at@^1.0.0:
   version "1.6.3"
   resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.6.3.tgz#6355d32cf1b04cdff6b484e5e711782b2f0c39be"

-"coffee-script<strong i="8">@github</strong>:jashkenas/coffeescript":
+coffee-script@jashkenas/coffeescript:
   version "1.11.1"
-  resolved "https://codeload.github.com/jashkenas/coffeescript/tar.gz/887052de079b2f0af9f080031a00bb7544eaca08"
+  resolved "https://codeload.github.com/jashkenas/coffeescript/tar.gz/0d132318ce8f7116a436d97db1f2a5c8b1dedf28"

 [email protected]:
   version "0.3.0"

有人可以写出导致锁文件被意外修改的场景吗? 这种变化是一个严重的变化,并且确实使锁文件成为二等公民,因为它要求对其进行显式更新,这意味着在记住哪些操作导致它被更新等方面需要大量开销。

我认为yarn install是为我构建 node_modules 的命令。
yarn addyarn remove相反,修改 package.json、yarn.lock 和清理 node_modules。
addremove相反,我运行install频率要高出 100 倍,尤其是在 CI 中,我从没想过会有副作用。

我不希望事情发生变化的示例:

  1. 我在 Yarn 0.15.0 上,我的队友在 Yarn 0.16.0 上。
    因为 0.16.0 每次我对由我的队友生成的 yarn.lock 运行yarn install时在 yarn.lock 中的条目之间添加了空格,所以我得到了一个修改过的 yarn.lock 文件,我需要记住不要提交。
    反之亦然。
  2. 我的其他构建工具依赖 yarn.lock 作为 node_modules 状态的“真实来源”。 如果它意外更改,我将在我的构建中获得不确定性

@小猫

问题是,如果锁文件默认是纯的,那么人们会忘记更新它,因为它是一个单独的命令。

想象一个场景,有人只是在使用 npm 并更新 package.json,yarn.lock 将如何更新?

如果我们假设yarn install不应该更新yarn.lock ,那么它也应该,如果失败, yarn.lock是同步的出来package.json凸显一个事实,即yarn install --save-lockfile需要让一切恢复同步。

+1 yarn install 不应该改变 yarn.lock

  1. 调试器是一个 oss 应用程序。 我们希望贡献者能够安装纱线并获得 _good_ 版本。 我们让人们 npm install 并说它因为传递属性而中断。 使用纱线安装,贡献者纱线安装并且不知道如何处理纱线锁更改。

我不担心更新锁定文件。 理想情况下,greenkeeper 会在 deps 更改时执行此操作,然后我们可以合并锁定文件更改。

我想用当前的想法更新这个问题。 @kittens和我都认为--pure-lockfile _not_应该是默认值,原因有几个。

它始于人们如何添加/删除/更新依赖项。 虽然有它的命令,但通常的做法是手动或通过其他工具(如Lerna )手动更新package.json

一旦您手动修改了package.json ,Yarn 和 npm 中的期望是,当您运行另一个安装它时,使用package.json _syncs_。 从这个意义上说, yarn install几乎可以重命名为yarn sync

关于同步主题,当您使用新的依赖项运行安装时,您希望node_modules目录反映这些更改。 由于yarn.lock充当node_modules的助手,您应该期望它以相同的方式保持同步。

你的package.json是真相的最终来源,它是你与纱线的接口,它是你的配置,它是你唯一应该关心的事情。 在理想的世界中,您只需提交yarn.lock ,然后就不必再考虑了。


附带说明一下,我相信许多对此问题表示支持的人对这里实际讨论的内容感到困惑。

默认情况下使用--pure-lockfile并不意味着 Yarn 不会产生一致和可靠的结果。 相同的package.json将产生相同的yarn.lock ,这将在 100% 的情况下产生相同的node_modules

当您更新package.json您的yarn.lock文件会更新,然后您的node_modules也会更新。 这是事物的一种非常自然的秩序,我们应该保持这种秩序


关于 CI 能够在您更新package.json但没有运行yarn install来同步所有我确定有人会提出的所有内容时获得不同的依赖项(尽管我不认为一个问题)——我和其他人一直在讨论关于集成 Yarn 的各种 CI 工具,如果人们认为这是一个大问题,我们可以很容易地推动他们默认使用--pure-lockfile


如果我们要进行此更改,则在更改依赖项时会更频繁地产生负面影响。 出于我列出的原因,我说我们应该关闭这个问题。

@thejameskyle如果您能澄清一些事情,我将不胜感激:

  1. 开发人员有一个package.json ,其中包含一个依赖项"foo": "^1.0.0"
  2. 开发人员运行yarn installfoo包当前版本1.0.0 ,因此它创建了一个yarn.lock文件,该文件锁定在[email protected]
  3. 开发人员将yarn.lock到 Git。
  4. 开发人员在他们本地的 repo 副本上运行单元测试,一切正常。
  5. 开发人员将他们的 repo 推送到 CI(例如 Travis)。
  6. CI 运行yarn install ,但foo现在已经更新到版本1.1.0 ,所以 Yarn 安装[email protected]并用新版本覆盖yarn.lock foo
  7. CI 中断是因为foo在版本1.1.0发生了重大变化

下面是一个类似的情况:

  1. 开发人员有一个package.json ,其中包含一个依赖项"foo": "^1.0.0" ,它被锁定为[email protected]yarn.lock保存在 Git 中。
  2. 单元测试在开发人员的本地 repo 副本上运行良好。
  3. 贡献者克隆 repo 的目的是进行修改 + 拉取请求。
  4. 当贡献者运行yarn install他们会得到[email protected] ,这会导致yarn.lock更新。
  5. 现在贡献者的构建被破坏了,因为foo在版本1.1.0发生了重大变化

我认为这些是大多数人担心的情况。

因此,如果您能澄清yarn install目前的行为存在上述问题,我认为这将消除我们的大部分担忧。 :+1:

这两种情况都不适用。 仅仅因为依赖项已更新并不意味着您会得到它,前提是您对package.json进行了更改。

我只是要结束这个问题,因为这似乎是人们唯一关心的问题,正如我所说的,这不是一个真实的场景。 这个问题很可能会引起更多的混乱。

但是如果从 github 安装依赖项,它确实有不好的行为,正如我上面报道的

@adamchainz这应该单独修复,我们可以轻松地将其锁定到提交

这两种情况都不适用。 仅仅因为依赖项已更新并不意味着您会得到它,前提是您对package.json进行了更改。

@thejameskyle :我不确定我是否理解为什么这不是真实场景。 你能详细说明一下吗?

想象一个记忆功能,其中输入是package.json ,输出是yarn.lock

  1. 第一次传递package.json它会创建一个yarn.lock并缓存结果。
  2. 下次运行 _that same_ package.json ,结果将完全相同,因为它已被缓存。
  3. 当您更改package.json您已使缓存无效,现在将重新计算yarn.lock

我们现在谈论的是摆脱#3,而是将yarn.lock视为它没有被更改的package.json失效。 这对于 memoize 函数来说真的很奇怪,对于 Yarn 来说也是一种非常奇怪的行为。

一个包在提交和新版本方面会发生什么_应该_无关紧要(如果我们有 git commits 的错误,那么我们应该单独修复它,但这与这个问题无关)。

它比我想象的要复杂(每个包版本都可以单独有效地“记忆”,更改一个包的版本不会使其余版本无效),但希望现在每个人都明白这一点。

@thejameskyle :为了清楚起见(和好奇心),假设我有一个包含yarn.lock文件的项目,并且有人拉下了存储库。 不运行yarn installnpm install ,此人向package.json文件添加新的依赖项,然后运行yarn install 。 在这种情况下,是否会完全忽略现有的yarn.lock文件?

这里发生了很多不同的事情,我想尝试解开(没有双关语)。

首先,人们提出了许多不同的要求,我认为这些要求是没有争议的(并且这些要求会使一些现有的行为成为错误,我很快就会谈到)。

来自原始错误报告。

根据环境(当前安装的纱线版本)修改锁文件时,一致性会丢失。
什么是预期行为?
安装 yarn 时不要写 yarn.lock 或 package.json。
要更新 yarn.lock 使用 yarn upgrade

更准确地说,在我看来,预期的语义是:

  • 如果package.json自上次yarn.lock更改后没有更改,则yarn.lock是事实来源,不应更新。
  • 如果package.json自上次以来发生了变化, yarn.lock发生了变化,则更新yarn.lock使其满足package.json并更新node_modules
  • 如果yarn update运行,重新解析所有依赖项并获取满足package.json的所有内容的最新版本。

这意味着当一个仓库第一次被克隆到一台机器上时,如果yarn.lock被签入,yarn 应该总是把它当作真实的来源,而不是对yarn.lock生成更新,然后跳转直接进入获取步骤。

在某种程度上,这不是纱线的当前行为,我认为这将是一个错误。


@esphen写道:

我同意。 应该首先讨论为什么 yarn install 默认写一个锁文件,因为它似乎与整个锁文件的概念不一致。 如果默认情况下不锁定版本,为什么要使用锁定文件?

我认为这是想说的是,如果现有的锁文件仍然是最新的,则纱线不应该写出新的锁文件。 我同意这一点。

我同意@bestander的观点,即默认情况下只有变异操作才应更新

这里的主要问题是对package.json的更改是否应该导致yarn.lock更新。 在我看来,如果到了改变package.json没有被满足yarn.lock ,就必须更新yarn.lock

锁定文件系统(如yarn)的一个重要不变式是,使用正常工作流程,开发人员可以确保在运行应用程序时实际使用的包与package.json指定的版本相匹配。 如果允许package.jsonyarn.lock不同步,这将是不正确的,唯一知道这一点的方法是让人类读者仔细阅读yarn.lock

大多数用户考虑锁文件的最佳方式是它是正在运行的纱线的工件,它代表当前package.json使用的所有包的精确版本。 通过签入,其他协作者、CI 和生产代码可以确保使用相同的版本。


@Guuz说:

因此,为了检查我是否正确理解这一点:
yarn 安装所有依赖项并修改锁文件。 在 CI 服务器上,您应该使用 yarn install --pure-lockfile?

这个问题呼应了一些人在这个线程中的观点。

Cargo 有一个--locked标志,表示“如果package.json不满足yarn.lock ,这是一个硬错误”。 Bundler 有一个类似的标志( --frozen ),它是在 Heroku 采用 Bundler 时添加的,如果人们对Gemfile进行本地更改并忘记检查Gemfile.lock

这个想法是,在您的正常开发过程中,您希望能够对package.json进行更改并让纱线确保yarn.lock保持同步(再次确保指定的版本在package.json始终匹配实际使用的内容)。

但是在部署时,发散实际上总是一个错误,因为这意味着您对package.json进行了更改,运行了本地yarn命令,而忘记签入yarn.lock . 这意味着package.json中的版本与应用程序运行时使用的实际版本不匹配,我们说这违反了 yarn 的基本不变量。


@esphen说:

在我看来,包管理器扮演的角色之一是尽可能轻松地开始项目开发。 一个简单的 yarn 安装应该可以获得您开始开发所需的所有包,而不会涉及任何混淆。

我认为这是没有争议的。

使用 npm 我有很多开发人员加入一个项目的实例,却发现一个项目在他们的机器上不起作用。 这些实例的发生是由于瞬态依赖性将版本碰撞到具有破坏性更改的版本或根本不遵循 semver。 我曾希望 yarn 能够解决这些问题,但如果项目的所有开发人员都应该运行 yarn install --pure-lockfile 以 100% 确定该项目将被构建,那么情况并非如此。

运行yarn install --pure-lockfile将意味着即使锁文件中的版本与package.json指定的版本冲突,也会遵守锁文件。 如果开发人员在更改package.json后忘记签入他们的yarn.lock ,那么这应该首先出现。

包管理器的另一个角色是让项目控制它们的依赖项。 如果默认情况下是纯的,开发人员可以查看过时的纱线以查看过时的版本,然后查看更改说明,避免任何破坏性更改。 这将使开发人员可以完全控制在给定的发布时间范围内只修改版本,而不是禁止开发人员执行 git commit -a 以避免意外的锁文件提交。

如果package.json没有改变,在我看来,如果yarn.lock得到更新,这是一个错误。 至少一个错误案例似乎在原始报告中:

根据环境(当前安装的纱线版本)修改锁文件。

我认为这是一个错误,应该纠正。

稍后在线程中, @thejameskyle说:

想象一个 memoize 函数,其中输入是 package.json,输出是 yarn.lock。

在我看来,这正是正确的心理模型(“当且仅当package.json更改时, yarn.lock才能更改”),如果抽象泄漏,我们应该修复它。


@adamchainz说:

关于以上的更多信息:我们的构建有来自 Github 的 coffeescript 作为子依赖。 coffeescript 推送了一些提交,我们在构建过程中通过运行 yarn install 得到了一个修改过的 yarn.lock

然后:

但是如果从 github 安装依赖项,它确实有不好的行为,正如我上面报道的

这里的问题是,yarn 没有将 git sha 视为 git 依赖项的锁定版本的一部分。 Cargo 和 Bundler 都有序列化到锁文件的“精确”版本的概念; 对于 git 源,“精确”版本是 SHA。 然后,当您仅使用package.jsonyarn.lock制作一个新的克隆并运行yarn ,获取您需要的代码所需的所有信息都在那里。

我必须承认,我在查看原始 git 代码时错过了这种交互; 代码中有一些 SHA 跟踪,但yarn install并不能确保水合依赖图尊重它。


TL; 博士

我同意@thejameskyle@kittens 的观点yarn.lock应该自动与package.json保持同步,因为我相信用户应该能够假设他们的package.json指定的版本与执行他们的应用程序时使用的内容对齐。

然而,即使package.json没有改变,似乎也有一些错误会导致yarn.lock中的不当流失:

  • 跨机器更改纱线版本更新锁文件
  • 即使package.json尚未更新,git 依赖项也会更新,然后更新锁文件

我们还应该考虑 Cargo 的--locked标志,如果开发人员更新package.json并且忘记签入更新的yarn.lock ,您可以在 CI 中使用它来快速失败构建

@thejameskyle谢谢! :heart: 我同意你和@kittens 的观点,即yarn.lock应该在更改package.json后更新

@wycats像往常一样非常详尽和有见地的帖子。 :+1: 我同意你的看法,我也喜欢--locked标志(或类似的)的想法。 我们应该为此创建一个新问题。

使 #1568 跟踪 git SHA 问题

@wycats ,感谢您的

这意味着当第一次在机器上克隆存储库时,如果签入了yarn.lock,yarn 应始终将其视为真实来源,而不是对yarn.lock 生成更新,并直接跳转到 fetch 步骤。
在某种程度上,这不是纱线的当前行为,我认为这将是一个错误。

这正是打开此问题的原因。
我们公司有几个活跃的 Yarn 版本,以我们的规模,我认为我们无法在任何地方进行原子更新。
尽管 package.json 是同步的,但基于 yarn 0.13、0.14 和 0.15 的构建在 yarn.lock 文件中引入了细微的变化。
这导致了一些问题,例如由于源树中的更改使缓存无效,Buck 构建速度变慢。
这导致我和几个团队工作了几个小时。

@thejameskyle ,感谢分享您的意见。
公平地说,我没有考虑 package.json 与 yarn.lock 不同步的情况。 你有一个有效的观点。

但是正如@wycats指出的那样,原始错误报告是有效的。
解决这个问题对于拥有有效的构建很重要,我将重新打开这个问题,目的是提出一个满足所有相关方的解决方案。

@wycats

更准确地说,在我看来,预期的语义是:

  • 如果package.json自上次yarn.lock更改后没有更改,则yarn.lock是事实来源,不应更新。
  • 如果package.json自上次以来发生了变化, yarn.lock发生了变化,则更新yarn.lock使其满足package.json并更新node_modules
  • 如果yarn update运行,重新解析所有依赖项并获取满足package.json的所有内容的最新版本。

这意味着当一个仓库第一次被克隆到一台机器上时,如果yarn.lock被签入,yarn 应该总是把它当作真实的来源,而不是对yarn.lock生成更新,然后跳转直接进入获取步骤。

这些是我在 #364 中添加的我们遵循的语义。

@bestander您参与了将这些启发式方法落实到位的公关(#364)。 您提议进行哪些额外更改?

这个问题非常广泛,我们已经同意--pure-lockfile不会是默认值,我们将遵循@wycats 概述的启发式方法。 如果此问题要保持开放,则标题需要反映此行为的当前问题。

@kittens听起来不错,我会更新问题。
或者当 package.json 没有改变时,也许我应该打开一个与安装更改锁文件相关的新文件

我们可以转到一个新问题吗? 这里的评论只能作为存档保存

听起来不错, @thejameskyle ,我今天会创建一个新问题并在此处链接

创建了新的重点问题https://github.com/yarnpkg/yarn/issues/1576

如果 package.json 中的包不在 yarn.lock 中,那么有一个选项让yarn install失败会很有趣,即。 如果任何包未锁定,则失败

在阅读上述内容后,添加对我来说仍然模棱两可的澄清:

tldr; package.json无关更改不会将软件包更新到与其未更改的package.json semver 兼容的最新版本。

根据上面的一些措辞,听起来yarn.lock被缓存在package.json哈希上,因此听起来yarn.lock将被写入(更新/缓存无效) 对package.json任何更改,这将是有问题的,因为不相关的更改(即更新到"description"或其他依赖项)可能会导致该依赖项的yarn.lock版本更新为同一现有package.json semver 中的较新版本。

但是,我验证了包的yarn.lock条目仅在更新相应的package.json semver 时才会写入(即使新的 semver 与现有的yarn.lock版本兼容,并且因此不需要版本更新)。

例如,

面包屑 #1576

顺便说一句,如果你愿意用这样的小文章为文档做出贡献,这对社区来说会很棒。
核心团队都在忙于解决问题和添加新功能,如果社区帮助维护文档,我们将不胜感激

@CrabDude感谢您分享您的澄清。

您的意思是 - 在上面的示例中 - 只有lodash及其自己的依赖项会在yarn.lock更新其锁定版本? 例如,即使另一个依赖项可能有一个新的锁定版本,它也不会同时更新?

或者第二个例子:假设yarn.lock严重过时,用户运行yarn add向 package.json 添加新的依赖项。 所有其他过时的软件包现在会在yarn.lock ,还是会保持不变?

@拉金斯

你的意思是 - 在你上面的例子中 - 只有 lodash 和它自己的依赖项才会在 yarn.lock 中更新它们的锁版本?

是的。 这在我的例子中似乎得到了支持。

所有其他过时的包现在会在 yarn.lock 中更新,还是会保持不变?

看起来非lodash依赖树/包的锁条目不会更新; 只有lodash的子依赖会是。

从我的角度来看,这些中的每一个都是可取的和预期的。

前言:我爱纱线。 但它让我沮丧无止境。

在我的公司,尽管从未更改package.json ,但yarn install在不同机器(每台运行相同版本)上不断更改锁文件。 当我们这样做时,我们使用yarn add 。 这很烦人,因为 CI 在构建后验证 git status 是否干净,以确保我们没有忘记执行诸如签入锁定文件之类的事情,并且它经常更改。

我对 yarn 的期望是它会确保所有机器上的 node_modules _默认_相同。 没有额外的标志。 它会优先考虑正确性而不是便利性。 如果我想要不确定性,我可以直接使用 npm。 当文件发生变化时,这对我来说是一个信号,表明它发生了变化,我应该仔细检查它。 它不应该改变。

问题

  • 是不是说虽然修改了lockfile,但是node_modules的内容总是和生成的时候一样? 我不相信是这种情况,但如果是这样,那么我理解这个线程中的困惑——这意味着纱线做了正确的事情,尽管它看起来没有。
  • package.json更改时,会重新生成锁文件。 根据特定程序员的 node_modules 的状态,这难道不会无意中改变很多依赖项吗? Yarn 应该确定一个增量并尝试尽可能地保留现有的锁(如果还没有)。
  • 为什么yarn add package.json^指定package.json版本? 再次,我理解纱线的承诺是冻结依赖项。

相关错误

  • node_modules的随机包被删除时, yarn install表示成功而无需重新安装它。 当其中很多都消失时,它会重新安装它们。 npm在这方面更彻底一些。
  • 如果您删除 node_modules 并进行全新安装,则锁文件往往会重新生成(这与您所期望的完全相反——我希望它完全安装锁文件中的内容并且绝对不执行其他任何操作)
  • 如果您在全新安装后不接触包或node_modules情况下删除锁文件,纱线会重新生成它,并且它通常与以前的版本大不相同。 这就像编译器每次运行时都会生成不同的代码,尽管什么都没做。

总体而言,yarn 使安装速度更快,但其核心(不)能力似乎失败了:默认情况下,始终如一地冻结版本。 我不需要帮助我开始我的项目的便利,我需要帮助在一个庞大的团队中多年维护它。 程序员是聪明的、有目的的,当他们想要改变时,他们会明确地提出要求。

不断变化的锁文件并没有灌输信心,而且是一个不断的麻烦。 我更喜欢 package.json 与锁定文件不匹配、锁定文件与 node_modules 不匹配、锁定版本不再存在等的警告和错误,因此它可以阻止我的构建死在他们的轨道上,我可以对我的依赖做出有意识的决定。

@jspiro ,感谢您写这篇文章。
这里提出了几个问题。
最好单独打开每个问题,否则它们会在评论中丢失。

您使用的是最新版本的 Yarn 吗?
从 0.18-0.19 开始,我们没有看到机器之间对 yarn.lock 文件的修改。

问题:

是不是说虽然修改了lockfile,但是node_modules的内容总是和生成的时候一样? 我不相信是这种情况,但如果是这样,那么我理解这个线程中的困惑——这意味着纱线做了正确的事情,尽管它看起来没有。

Dev 和可选的依赖项可以被排除在同一个锁文件之外。
但是安装了 bing 的那些,除了平台特定的包,node_modules 应该在相同的地方有相同的包。

当 package.json 更改时,会重新生成锁定文件。 根据特定程序员的 node_modules 的状态,这难道不会无意中改变很多依赖项吗? Yarn 应该确定一个增量并尝试尽可能地保留现有的锁(如果还没有)。

这是一个很好的功能请求,很想看到一个 PR。

为什么yarn在package.json中用^添加指定版本? 再次,我理解纱线的承诺是冻结依赖项。

这反映了 npm 的行为。
您可以为确切版本执行yarn add [email protected]yarn add is-array --exact
也许在某个时候我们应该将精确版本设为默认值,这可以在 RFC 中进行讨论。

当 node_modules 中的一个随机包被删除时,yarn install 说成功而不重新安装它。 当其中很多都消失时,它会重新安装它们。 npm 在这方面更彻底一些。

默认情况下,Yarn 运行快速浅层检查。
进行更深入的检查会更慢,但我们正在努力,我知道如何进行快速的深入检查。
但是,您不应该接触 node_modules 中的文件,验证每个文件进行修改会导致安装体验非常缓慢。
如果您想跳过浅层检查,请在安装前删除node_modules/.yarn-integrity文件。 这不是官方的,可能会发生变化。
官方方法是运行yarn install --force ,它会强制完全安装,但它会重写 yarn.lock 作为副作用。

如果您删除 node_modules 并进行全新安装,则锁文件往往会重新生成(这与您所期望的完全相反——我希望它完全安装锁文件中的内容并且绝对不执行其他任何操作)

好久没看到这个了
如果可以重现,请打开一个问题并抄送给我。

如果在全新安装后删除锁文件而不触及 package 或 node_modules,yarn 会重新生成它,并且它通常与以前的版本大不相同。 这就像编译器每次运行时都会生成不同的代码,尽管什么都没做。

一段时间后,可能会发布新版本的传递依赖项。
因此,由于提升逻辑,node_modules 的结构可能会发生显着变化。
这按设计工作。
import命令来https://github.com/yarnpkg/yarn/pull/2580。
这将允许您从现有的 node_modules 生成锁定文件。

@jspiro ,Yarn 是一个年轻的社区驱动项目,欢迎您的 PR 使其更好地为您工作。

有机会至少获得一个选项来设置所需的默认行为吗?

目前我们正在修复这个问题https://github.com/yarnpkg/yarn/issues/3490 ,有时yarn install可能会导致锁文件被优化,这不是预期的行为,我们会修复它。
这可能是您要求进行此更改的原因,否则仅当您手动更改 package.json 时, yarn.lock 文件才应更改。

您可以在 .yarnrc 中将 --pure-lockfile/--frozen-lockfile 设置为 true ,默认情况下它将附加到安装命令中:

--install.pure-lockfile true

我的问题是,如果我不使用 pure-lockfile,我会安装错误版本的依赖项。 它与不需要的 yarn.lock 更改无关

您可以提交有关重现步骤的问题吗?
我们会解决的

package.jsonyarn.lock由于开发人员错误地通过npm install --save而不是yarn add添加依赖项而失去同步时,我也被这个问题所困扰。

我不同意pure-lockfile应该是默认值,并认为frozen-lockfile应该是yarn install的默认值。

如果yarn.lockpackage.json不同步,则frozen-lockfile产生错误消息。 frozen-lockfile因此在构建机器(即 jenkins)上非常有用,因为它会将这些构建标记为失败,正如预期的那样。

然后由开发人员决定在 package.json / yarn.lock 中添加哪个版本。

不幸的默认yarn install只会获取尚未锁定在依赖项中的最新版本,并编写更新版本yarn.lock ,它永远不会成为项目的一部分。 因此,允许将来由于意外的版本碰撞而中断构建。 这就是我们开始使用锁文件的原因。

要点应该是:

只有像addremoveupgrade应该改变yarn.lock

install应该这样做,即要么在锁定的版本中安装依赖项,要么在检测到package.jsonyarn.lock之间不匹配时失败。 (唯一的例外是,如果一开始就没有yarn.lock 。然后,并且只有这样,它才可能创建一个,但它永远、永远都不应该再次触摸它。)

因此,frozen-lockfile 在构建机器(即 jenkins)上非常有用,因为这些构建将失败。

我认为当我们检测到我们处于 CI 模式时,我们可以自动启用它吗?

@BYK在添加到此处之前,我没有意识到此问题已关闭。 我应该开一个新的还是可以重新打开?

我会说开一个新的☺️

我同意@thejameskyle@kittens 的观点,即 yarn.lock 应该自动与 package.json 保持同步

不确定这是否已经说过,但以防万一:当 package.json 中的任何内容发生更改时,您不必使整个 yarn.lock 无效。 您只能使在 package.json 中修改的包的依赖项无效。 Fe 如果您只更新了 TypeScript,则需要修改 TypeScript 的依赖项(考虑到其他未更改的包)。

此页面是否有帮助?
0 / 5 - 0 等级