您是要请求一个 _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
我同意。 应该首先讨论为什么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.json
, yarn.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 add
和yarn remove
相反,修改 package.json、yarn.lock 和清理 node_modules。
与add
和remove
相反,我运行install
频率要高出 100 倍,尤其是在 CI 中,我从没想过会有副作用。
我不希望事情发生变化的示例:
yarn install
时在 yarn.lock 中的条目之间添加了空格,所以我得到了一个修改过的 yarn.lock 文件,我需要记住不要提交。@小猫
问题是,如果锁文件默认是纯的,那么人们会忘记更新它,因为它是一个单独的命令。
想象一个场景,有人只是在使用 npm 并更新 package.json,yarn.lock 将如何更新?
如果我们假设yarn install
不应该更新yarn.lock
,那么它也应该,如果失败, yarn.lock
是同步的出来package.json
凸显一个事实,即yarn install --save-lockfile
需要让一切恢复同步。
+1 yarn install 不应该改变 yarn.lock
我不担心更新锁定文件。 理想情况下,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如果您能澄清一些事情,我将不胜感激:
package.json
,其中包含一个依赖项"foo": "^1.0.0"
yarn install
。 foo
包当前版本1.0.0
,因此它创建了一个yarn.lock
文件,该文件锁定在[email protected]
yarn.lock
到 Git。yarn install
,但foo
现在已经更新到版本1.1.0
,所以 Yarn 安装[email protected]
并用新版本覆盖yarn.lock
foo
foo
在版本1.1.0
发生了重大变化下面是一个类似的情况:
package.json
,其中包含一个依赖项"foo": "^1.0.0"
,它被锁定为[email protected]
, yarn.lock
保存在 Git 中。yarn install
他们会得到[email protected]
,这会导致yarn.lock
更新。foo
在版本1.1.0
发生了重大变化我认为这些是大多数人担心的情况。
因此,如果您能澄清yarn install
目前的行为不存在上述问题,我认为这将消除我们的大部分担忧。 :+1:
这两种情况都不适用。 仅仅因为依赖项已更新并不意味着您会得到它,前提是您对package.json
进行了更改。
我只是要结束这个问题,因为这似乎是人们唯一关心的问题,正如我所说的,这不是一个真实的场景。 这个问题很可能会引起更多的混乱。
但是如果从 github 安装依赖项,它确实有不好的行为,正如我上面报道的
@adamchainz这应该单独修复,我们可以轻松地将其锁定到提交
这两种情况都不适用。 仅仅因为依赖项已更新并不意味着您会得到它,前提是您对
package.json
进行了更改。
@thejameskyle :我不确定我是否理解为什么这不是真实场景。 你能详细说明一下吗?
想象一个记忆功能,其中输入是package.json
,输出是yarn.lock
。
package.json
它会创建一个yarn.lock
并缓存结果。package.json
,结果将完全相同,因为它已被缓存。package.json
您已使缓存无效,现在将重新计算yarn.lock
。我们现在谈论的是摆脱#3,而是将yarn.lock
视为它没有被更改的package.json
失效。 这对于 memoize 函数来说真的很奇怪,对于 Yarn 来说也是一种非常奇怪的行为。
一个包在提交和新版本方面会发生什么_应该_无关紧要(如果我们有 git commits 的错误,那么我们应该单独修复它,但这与这个问题无关)。
它比我想象的要复杂(每个包版本都可以单独有效地“记忆”,更改一个包的版本不会使其余版本无效),但希望现在每个人都明白这一点。
@thejameskyle :为了清楚起见(和好奇心),假设我有一个包含yarn.lock
文件的项目,并且有人拉下了存储库。 不运行yarn install
或npm 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.json
与yarn.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.json
和yarn.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 ,我今天会创建一个新问题并在此处链接
如果 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
版本兼容,并且因此不需要版本更新)。
例如,
yarn add lodash@^4.17.1
安装[email protected]
[email protected]
可用。[email protected]
package.json
被改变(或者 yarn add/upgrade/remove 是专门针对 lodash 运行的)。面包屑 #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。 当文件发生变化时,这对我来说是一个信号,表明它发生了变化,我应该仔细检查它。 它不应该改变。
问题
package.json
更改时,会重新生成锁文件。 根据特定程序员的 node_modules 的状态,这难道不会无意中改变很多依赖项吗? Yarn 应该确定一个增量并尝试尽可能地保留现有的锁(如果还没有)。yarn add
package.json
用^
指定package.json
版本? 再次,我理解纱线的承诺是冻结依赖项。相关错误
node_modules
的随机包被删除时, yarn install
表示成功而无需重新安装它。 当其中很多都消失时,它会重新安装它们。 npm
在这方面更彻底一些。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.json
和yarn.lock
由于开发人员错误地通过npm install --save
而不是yarn add
添加依赖项而失去同步时,我也被这个问题所困扰。
我不同意pure-lockfile
应该是默认值,并认为frozen-lockfile
应该是yarn install
的默认值。
如果yarn.lock
和package.json
不同步,则frozen-lockfile
产生错误消息。 frozen-lockfile
因此在构建机器(即 jenkins)上非常有用,因为它会将这些构建标记为失败,正如预期的那样。
然后由开发人员决定在 package.json / yarn.lock 中添加哪个版本。
不幸的默认yarn install
只会获取尚未锁定在依赖项中的最新版本,并编写更新版本yarn.lock
,它永远不会成为项目的一部分。 因此,允许将来由于意外的版本碰撞而中断构建。 这就是我们开始使用锁文件的原因。
要点应该是:
只有像add
、 remove
和upgrade
应该改变yarn.lock
。
install
应该这样做,即要么在锁定的版本中安装依赖项,要么在检测到package.json
和yarn.lock
之间不匹配时失败。 (唯一的例外是,如果一开始就没有yarn.lock
。然后,并且只有这样,它才可能创建一个,但它永远、永远都不应该再次触摸它。)
因此,frozen-lockfile 在构建机器(即 jenkins)上非常有用,因为这些构建将失败。
我认为当我们检测到我们处于 CI 模式时,我们可以自动启用它吗?
@BYK在添加到此处之前,我没有意识到此问题已关闭。 我应该开一个新的还是可以重新打开?
我会说开一个新的☺️
我同意@thejameskyle和@kittens 的观点,即 yarn.lock 应该自动与 package.json 保持同步
不确定这是否已经说过,但以防万一:当 package.json 中的任何内容发生更改时,您不必使整个 yarn.lock 无效。 您只能使在 package.json 中修改的包的依赖项无效。 Fe 如果您只更新了 TypeScript,则需要修改 TypeScript 的依赖项(考虑到其他未更改的包)。
最有用的评论
这里发生了很多不同的事情,我想尝试解开(没有双关语)。
首先,人们提出了许多不同的要求,我认为这些要求是没有争议的(并且这些要求会使一些现有的行为成为错误,我很快就会谈到)。
来自原始错误报告。
更准确地说,在我看来,预期的语义是:
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写道:
我认为这是想说的是,如果现有的锁文件仍然是最新的,则纱线不应该写出新的锁文件。 我同意这一点。
这里的主要问题是对
package.json
的更改是否应该导致yarn.lock
更新。 在我看来,如果到了改变package.json
没有被满足yarn.lock
,就必须更新yarn.lock
。锁定文件系统(如yarn)的一个重要不变式是,使用正常工作流程,开发人员可以确保在运行应用程序时实际使用的包与
package.json
指定的版本相匹配。 如果允许package.json
与yarn.lock
不同步,这将是不正确的,唯一知道这一点的方法是让人类读者仔细阅读yarn.lock
。大多数用户考虑锁文件的最佳方式是它是正在运行的纱线的工件,它代表当前
package.json
使用的所有包的精确版本。 通过签入,其他协作者、CI 和生产代码可以确保使用相同的版本。@Guuz说:
这个问题呼应了一些人在这个线程中的观点。
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 install --pure-lockfile
将意味着即使锁文件中的版本与package.json
指定的版本冲突,也会遵守锁文件。 如果开发人员在更改package.json
后忘记签入他们的yarn.lock
,那么这应该首先出现。如果
package.json
没有改变,在我看来,如果yarn.lock
得到更新,这是一个错误。 至少一个错误案例似乎在原始报告中:我认为这是一个错误,应该纠正。
稍后在线程中, @thejameskyle说:
在我看来,这正是正确的心理模型(“当且仅当
package.json
更改时,yarn.lock
才能更改”),如果抽象泄漏,我们应该修复它。@adamchainz说:
然后:
这里的问题是,yarn 没有将 git sha 视为 git 依赖项的锁定版本的一部分。 Cargo 和 Bundler 都有序列化到锁文件的“精确”版本的概念; 对于 git 源,“精确”版本是 SHA。 然后,当您仅使用
package.json
和yarn.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 中使用它来快速失败构建