我刚刚升级到npm @ 5.我现在有一个package-lock.json文件,其中包含package.json中的所有内容.我希望,当我运行时npm install
,将从锁定文件中提取依赖版本以确定应该在我的node_modules目录中安装什么.奇怪的是它实际上最终修改并重写了我的package-lock.json文件.
例如,锁定文件的typescript指定为版本2.1.6.然后,在npm install
命令之后,版本更改为2.4.1.这似乎打败了锁定文件的整个目的.
我错过了什么?如何让npm真正尊重我的锁文件?
1> jotaen..:
更新3:正如其他答案所指出的那样,该npm ci
命令在npm 5.7.0中引入,作为在CI上下文中实现快速且可重现的构建的另一种方式.有关详细信息,请参阅文档和npm博客.
更新2:更新和澄清文档的问题是GitHub问题#18103.
更新1:下面描述的行为在npm 5.4.2中得到修复:GitHub问题#17979中概述了当前预期的行为.
原始答案:在问题#16866中讨论的npm 5.1.0中的行为package-lock.json
发生了变化.您观察到的行为显然是从版本5.1.0开始的npm.
这意味着只要找到一个新版本的依赖项,package.json
就可以胜过.如果要有效地固定依赖关系,现在必须指定没有前缀的版本,例如,您需要将它们编写为而不是或.然后,和的组合将产生可重复的构建.要明确:单独不再锁定根级依赖项!package-lock.json
package.json
1.2.0
~1.2.0
^1.2.0
package.json
package-lock.json
package-lock.json
无论这个设计决定是否合适都是有争议的,因此在问题#17979中对GitHub的混淆导致了持续的讨论.(在我看来,这是一个值得怀疑的决定;至少这个名字lock
不再适用.)
还有一个注意事项:对不支持不可变包的注册表也有限制,例如直接从GitHub而不是npmjs.org提取包时.有关进一步说明,请参阅包锁的此文档.
真是一团糟!世界上最大的软件包管理器,但它没有关于它应该如何工作的文档.每个人都在猜测它应该做什么,它变成了一场意见之战.讨论是好的,但应该在释放到野外之前发生.在某些时候,某人需要进行最后的调用,然后才能实现,记录和发布.PHP是由委员会设计的,并且是ad-hoc'd一起,看看结果如何.我不愿意看到同样的事情发生在这个关键且广泛使用的工具上.
那么,使用package-lock有什么意义呢?我认为它会在不同的工作空间中创建相同的环境但事实证明它什么都不做
什么黑客是'npm update`呢?:○我有同样的感觉,`NPM install`更新DEPS,但我并不想相信它..但好像它是可悲的是真实的.不管怎么样还是有选择使用`NPM shrinkwrap`锁定DEPS,但肯定名称package-lock是不正确的,因为它不会冻结,也不会锁定依赖项.
"然后,package.json和package-lock.json的组合将产生可重现的构建." "package-lock.json"在这里有什么作用?如果没有使用版本前缀,单独"package.json"是否已经产生可重现的构建?
@JānisElmeris我认为package.json无法锁定深度依赖关系......
@LandonPoch不确定您对PHP的评论是指什么,但是Composer是一个比NPM(和yarn)更好的软件包管理器。听起来您可能有一段时间没有签出PHP了。
纱线没有这个问题。它会完全安装package-lock中列出的内容。
我真的很困惑......那么,1)我应该如何将完全锁定的包树部署到分段?只是"npm i --no-save"?2)如何在dev中更新软件包以准备新版本?"npm up --save"?老实说,我预计会有一个单独的命令从package-lock.json文件生成树
2> Ivan Shcherb..:
我发现将有一个新版本的npm 5.7.1使用new命令npm ci
,它将package-lock.json
仅安装
新的npm ci命令仅从您的锁文件安装.如果你的package.json和你的锁文件不同步,那么它将报告错误.
它的工作原理是丢弃你的node_modules并从头开始重新创建它.
除了保证你只获得锁文件中的内容之外,当你没有以node_modules开头时,它也比npm安装快得多(2x-10x!).
正如您可能从名称中获取的那样,我们希望它对持续集成环境来说是一个巨大的好处.我们还期望那些使用git标签进行生产部署的人将获得重大收益.
如果存在锁定文件,这应该是默认行为.
所以他们改变了我的工作方式,只是为了几个月后才把它带回来?
3> Gal Margalit..:
使用新推出的
npm ci
npm ci承诺给大型团队带来最大利益.让开发人员能够"签署"程序包锁定可以促进大型团队之间更有效的协作,并且能够准确安装锁定文件中的内容,有可能每月节省数十(如果不是数百)开发人员小时数,从而解放团队花更多的时间来建造和运送惊人的东西.
介绍npm ci
更快,更可靠的构建
@ phouse512这是对的.我们几乎_only_使用`npm ci`,如果更新或安装新软件包,只使用`npm install`.
这对我来说似乎是对的吗?谁能确认吗?
4> Ahmad Abdelg..:
简答:
当package-lock.json存在时,它会否决package.json
当package.json被修改时,它会否决package-lock.json
这是一个可以解释事物的场景(使用NPM 6.3.0验证)
你在package.json中声明了一个依赖,如:
"depA": "^1.0.0"
然后你这样做,npm install
它将生成一个package-lock.json:
"depA": "1.0.0"
几天后,一个较新的次要版本的"depA"被释放,比如说"1.1.0",那么下面的说法是正确的:
npm ci # respects only package-lock.json and installs 1.0.0
npm install # also, respects the package-lock version and keeps 1.0.0 installed
# (i.e. when package-lock.json exists, it overrules package.json)
接下来,您手动将package.json更新为:
"depA": "^1.1.0"
然后重新运行:
npm ci # will try to honor package-lock which says 1.0.0
# but that does not satisfy package.json requirement of "^1.1.0"
# so it would throw an error
npm install # installs "1.1.0" (as required by the updated package.json)
# also rewrites package-lock.json version to "1.1.0"
# (i.e. when package.json is modified, it overrules the package-lock.json)
这确实是“锁定”文件的预期行为。显然,较旧版本的NPM并非如此。
@LahiruChandima它并不真正跟踪更新。除非npm install不满足package.json的要求,否则它将使用package-lock.json的锁定版本,在这种情况下,它将安装package.json并相应地重建package-lock.json。如果您以某种方式更改了package.json,以使现有的package-lock仍然满足更新后的package.json,它将继续使用该package-lock
5> Daniel Tonon..:
使用npm ci
命令而不是npm install
.
"ci"代表"干净安装".它将基于package-lock.json文件而不是lenient package.json文件依赖项来安装项目依赖项.
它将为您的其他队友提供相同的构建,并且速度也更快.
ci是指“持续集成”,如在文档和博客文章中宣布该命令的内容所提及:http://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable
6> Daniel Tonon..:
看来此问题已在npm v5.4.2中修复
https://github.com/npm/npm/issues/17979
(向下滚动到线程中的最后一条注释)
更新资料
实际在5.6.0中已修复。5.4.2中存在一个跨平台错误,导致该问题仍然存在。
https://github.com/npm/npm/issues/18712
更新2
在这里查看我的答案:https :
//stackoverflow.com/a/53680257/1611058
npm ci
是现在安装现有项目时应使用的命令。
我正在使用5.4.2,它仍然导致在`npm i`时对package-lock.json的修改。例如,当我在不支持fsevents的机器上执行npm i时,将删除模块fsevents,然后当在不支持fsevents的计算机上再次执行npm i时,将模块重新添加。
7> Timothy Higi..:
将来,您将能够使用--from-lock-file
(或类似)标志仅在package-lock.json
不修改它的情况下安装.
这对于可重复构建很重要的CI等环境非常有用.
有关该功能的跟踪,请参阅https://github.com/npm/npm/issues/18286.
@YevgeniyAfanasyev而不是那个标志,它被实现为`npm ci`,它也处理你的问题.
8> Matt..:
你可能有类似的东西:
"typescript":"~2.1.6"
在您的package.json
哪个npm更新到最新的次要版本,在您的情况下2.4.1
编辑:来自OP的问题
但这并不能解释为什么"npm install"会改变锁定文件.锁文件不是要创建可重现的构建吗?如果是这样,无论semver值如何,它仍应使用相同的2.1.6版本.
回答:
这旨在锁定完整的依赖关系树.让我们说typescript v2.4.1
需要widget ~v1.0.0
.当你npm安装它抓住widget v1.0.0
.稍后您的开发人员(或CI版本)会执行npm安装并获取typescript v2.4.1
但widget
已更新为widget v1.0.1
.现在您的节点模块不同步.这是package-lock.json
阻止的.
或者更一般地说:
举个例子,考虑一下
包A:
{"name":"A","version":"0.1.0","依赖项":{"B":"<0.1.0"}}
包B:
{"name":"B","version":"0.0.1","依赖项":{"C":"<0.1.0"}}
和包C:
{"name":"C","version":"0.0.1"}
如果这些是注册表中唯一可用的A,B和C版本,那么将安装正常的npm安装A:
A@0.1.0 - B@0.0.1 - C@0.0.1
但是,如果发布了B@0.0.2,那么将安装新的npm安装A:
假设新版本没有修改B的依赖关系,则为A@0.1.0 - B@0.0.2 - C@0.0.1.当然,新版本的B可能包含新版本的C和任意数量的新依赖项.如果不希望这样的改变,A的作者可以指定对B@0.0.1的依赖.但是,如果A的作者和B的作者不是同一个人,那么A的作者就没有办法说当B完全没有改变时他或她不想拉入新出版的C版本.
OP问题2:让我看看我是否理解正确.您所说的是锁文件指定了辅助依赖项的版本,但仍然依赖于package.json的模糊匹配来确定顶级依赖项.那是准确的吗?
答:没有.package-lock锁定整个包树,包括中描述的根包package.json
.如果typescript
被锁定2.4.1
在你的位置package-lock.json
,它应该保持这种状态直到它被改变.并且让我们说明天typescript
发布版本2.4.2
.如果我签出你的分支并运行npm install
,npm将尊重lockfile并安装2.4.1
.
更多信息package-lock.json
:
对于npm修改node_modules树或package.json的任何操作,都会自动生成package-lock.json.它描述了生成的确切树,以便后续安装能够生成相同的树,而不管中间依赖性更新.
此文件旨在提交到源存储库,并用于各种目的:
描述依赖关系树的单个表示,以确保队友,部署和持续集成能够安装完全相同的依赖关系.
为用户提供一种"时间旅行"到node_modules的先前状态的工具,而无需提交目录本身.
通过可读的源代码控制差异来促进树更改的更大可见性.
并通过允许npm跳过以前安装的软件包的重复元数据解析来优化安装过程.
https://docs.npmjs.com/files/package-lock.json
但这并不能解释为什么"npm install"会改变锁定文件.锁文件不是要创建可重现的构建吗?如果是这样,无论semver值如何,它仍应使用相同的2.1.6版本.
我不明白.如果后续安装可能仍然进行升级,这是一个"锁定"文件?!
我遇到过同样的问题.在我们的CI/CD中,`package-lock.json`被拉下来然后我们运行`npm install`,但是`package-lock.json`文件被修改了,我们必须执行重置才能拉出接下来的变化
我认为他们开始时想把这个文件作为"信息"和"锁定",然后决定它只是一个"信息"文件.更好的名字是"package-info.json".我希望有一个"npm install -lock",它将从"package-lock.json"安装并忽略"package.json"
这就是我说的话.我的包锁文件说typescript@2.1.6但是当我运行npm install时,该条目被替换为typescript@2.4.1.
对我来说,这个答案并没有真正解决问题.特别是OP2的答案我无法重现; 事实上,npm 5.3.0在我的机器上的行为并不像这样.比方说,如果在`package.json`中使用`~2.1.6`指定了typescript,npm仍然会忽略锁文件中输出的内容.