Why does “npm install” rewrite package-lock.json?
我刚升级到NPM@5。我现在有一个package-lock.json文件,包含package.json中的所有内容。当我运行
例如,锁定文件的typescript被指定为2.1.6版本。然后,在执行
我错过了什么?如何让NPM真正尊重我的锁文件?
更新3:正如其他答案所指出的那样,在NPM5.7.0中引入了
更新2:更新和澄清文件的问题是Github问题18103。
更新1:下面描述的行为在NPM 5.4.2中得到了修正:目前预期的行为在Github发行17979中概述。
原始答案:如16866号问题所述,在NPM 5.1.0中,
这意味着,只要在
无论这个设计决策是好是坏,都是有争议的,因为在17979年的问题中对Github的混淆,有一个持续的讨论。(在我看来,这是一个值得怀疑的决定;至少
另一个注意事项:对于不支持不可变包的注册中心也有一个限制,例如当您直接从github而不是npmjs.org中提取包时。有关进一步的说明,请参阅此软件包锁文档。
我发现将有一个新版本的NPM 5.7.1和新的命令
The new npm ci command installs from your lock-file ONLY. If your package.json and your lock-file are out of sync then it will report an error.
It works by throwing away your node_modules and recreating it from scratch.
Beyond guaranteeing you that you'll only get what is in your lock-file it's also much faster (2x-10x!) than npm install when you don't start with a node_modules.
As you may take from the name, we expect it to be a big boon to continuous integration environments. We also expect that folks who do production deploys from git tags will see major gains.
号
使用新引进的
1 | npm ci |
npm ci promises the most benefit to large teams. Giving developers the ability to"sign off" on a package lock promotes more efficient collaboration across large teams, and the ability to install exactly what is in a lockfile has the potential to save tens if not hundreds of developer hours a month, freeing teams up to spend more time building and shipping amazing things.
号
引入
简短回答:
- 当package-lock.json存在时,它会否决package.json
- 当package.json被修改时,它会否决package-lock.json
小精灵
这里有一个场景可以解释问题(用NPM 6.3.0验证)
在package.json中声明依赖项,如下所示:
1 | "depA":"^1.0.0" |
号
然后,您可以这样做,
1 | "depA":"1.0.0" |
几天后,"DEPA"的一个较新的次要版本发布了,比如说"1.1.0",那么下面的内容是正确的:
1 2 3 4 | 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更新为:
1 | "depA":"^1.1.0" |
然后重新运行:
1 2 3 4 5 6 7 | 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) |
。
使用
"CI"代表"清洁安装"。它将基于package-lock.json文件安装项目依赖项,而不是基于lenient package.json文件依赖项。
它将生成与其他队友相同的构建,而且速度也快得多。
你可能有这样的东西:
1 | "typescript":"~2.1.6" |
在您的
Edit: Question from OP
But that doesn't explain why"npm install" would change the lock file. Isn't the lock file meant to create a reproducible build? If so,
regardless of the semver value, it should still use the same 2.1.6
version.Answer:
This is intended to lock down your full dependency tree. Let's say
typescript v2.4.1 requireswidget ~v1.0.0 . When you npm install it
grabswidget v1.0.0 . Later on your fellow developer (or CI build)
does an npm install and getstypescript v2.4.1 butwidget has been
updated towidget v1.0.1 . Now your node module are out of sync. This
is whatpackage-lock.json prevents.Or more generally:
As an example, consider
package A:
{ "name":"A", "version":"0.1.0", "dependencies": {
"B":"<0.1.0" } }package B:
{ "name":"B", "version":"0.0.1", "dependencies": {
"C":"<0.1.0" } }and package C:
{ "name":"C", "version":"0.0.1" }
If these are the only versions
of A, B, and C available in the registry, then a normal npm install A
will install:[email protected] -- [email protected]
-- [email protected]However, if [email protected] is published, then a fresh npm install A will install:
[email protected] -- [email protected]
-- [email protected] assuming the new version did not modify B's dependencies. Of course, the new version of B could include a new
version of C and any number of new dependencies. If such changes are
undesirable, the author of A could specify a dependency on [email protected].
However, if A's author and B's author are not the same person, there's
no way for A's author to say that he or she does not want to pull in
newly published versions of C when B hasn't changed at all.
号
OP Question 2: So let me see if I understand correctly. What you're
saying is that the lock file specifies the versions of the secondary
dependencies, but still relies on the fuzzy matching of package.json
to determine the top-level dependencies. Is that accurate?Answer: No. package-lock locks the entire package tree, including the
root packages described inpackage.json . Iftypescript is locked
at2.4.1 in yourpackage-lock.json , it should remain that way until it is
changed. And lets say tomorrowtypescript releases version2.4.2 .
If I checkout your branch and runnpm install , npm will respect the
lockfile and install2.4.1 .
号
关于
package-lock.json会自动为npm修改node_modules树或package.json的任何操作生成。它描述了生成的确切树,这样以后的安装就能够生成相同的树,而不管中间的依赖更新是什么。
此文件旨在提交到源存储库中,并具有多种用途:
Describe a single representation of a dependency tree such that teammates, deployments, and continuous integration are guaranteed to install exactly the same dependencies.
Provide a facility for users to"time-travel" to previous states of node_modules without having to commit the directory itself.
To facilitate greater visibility of tree changes through readable source control diffs.
And optimize the installation process by allowing npm to skip repeated metadata resolutions for previously-installed packages.
号
https://docs.npmjs.com/files/package-lock.json
将来,您将能够使用EDOCX1(或类似的)标志仅从EDOCX1(或2)安装,而无需修改它。
这对CI等环境非常有用,因为在这些环境中,可复制的构建非常重要。
请参阅https://github.com/npm/npm/issues/18286了解功能的跟踪。
这个问题似乎在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
在他们的Github页面上有一个开放的问题:https://github.com/npm/npm/issues/18712
当开发人员使用不同的操作系统时,这个问题最严重。
编辑:名字"锁"是一个棘手的一个,它的NPM试图赶上纱。它不是一个锁定的文件。
(希望经过这么多的否决后,我的回答更清楚)
一个简单的答案是:
至于这个棘手的名字,它的新产品管理试图赶上纱。