我最近刚升级到npm@5。我现在有一个包锁。包含package.json中的所有内容的Json文件。我希望,当我运行npm install时,依赖版本将从锁文件中提取,以确定应该在我的node_modules目录中安装什么。奇怪的是,它实际上最终修改和重写了我的包锁。json文件。
例如,锁文件的typescript被指定为2.1.6版本。然后,在执行npm install命令后,版本被更改为2.4.1。这似乎违背了锁文件的全部目的。
我错过了什么?我如何让npm尊重我的锁文件?
我最近刚升级到npm@5。我现在有一个包锁。包含package.json中的所有内容的Json文件。我希望,当我运行npm install时,依赖版本将从锁文件中提取,以确定应该在我的node_modules目录中安装什么。奇怪的是,它实际上最终修改和重写了我的包锁。json文件。
例如,锁文件的typescript被指定为2.1.6版本。然后,在执行npm install命令后,版本被更改为2.4.1。这似乎违背了锁文件的全部目的。
我错过了什么?我如何让npm尊重我的锁文件?
当前回答
这个问题在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是你现在安装现有项目时应该使用的命令。
其他回答
这个问题在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是你现在安装现有项目时应该使用的命令。
更新3:正如其他答案所指出的,npm ci命令在npm 5.7.0中被引入,作为在ci环境中实现快速和可复制构建的额外方式。更多信息请参阅文档和npm博客。
更新2:更新和澄清文档的问题是GitHub issue #18103。
更新1:下面描述的行为在npm 5.4.2中得到了修复:当前预期的行为在GitHub issue #17979中概述。
原答案(5.4.2之前):包锁的行为。Json在NPM 5.1.0中被改变了,在第16866期讨论过。你观察到的这种行为显然是npm 5.1.0版本的意图。
就是那个包裹。Json可以覆盖包锁。每当在package.json中发现一个依赖项的新版本时,就调用Json。如果你想有效地固定依赖项,你现在必须指定不带前缀的版本,例如,你需要把它们写成1.2.0而不是~1.2.0或^1.2.0。然后组合包装。Json和包锁。Json将产生可复制的构建。需要明确的是:package-lock。Json单独不再锁定根级依赖!
无论这个设计决定是好是坏是有争议的,在GitHub上的17979号问题中,有一个正在进行的讨论。(在我看来,这是一个值得怀疑的决定;至少这个名字锁不再适用了。)
另一个边注:对于不支持不可变包的注册表也有限制,例如当你直接从GitHub而不是npmjs.org提取包时。有关进一步的解释,请参阅包锁的文档。
你可能会遇到这样的情况:
"typescript":"~2.1.6"
在你的包裹里。NPM将它更新到最新的小版本,在你的例子中是2.4.1
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 requires widget ~v1.0.0. When you npm install it grabs widget v1.0.0. Later on your fellow developer (or CI build) does an npm install and gets typescript v2.4.1 but widget has been updated to widget v1.0.1. Now your node module are out of sync. This is what package-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: A@0.1.0 -- B@0.0.1 -- C@0.0.1 However, if B@0.0.2 is published, then a fresh npm install A will install: A@0.1.0 -- B@0.0.2 -- C@0.0.1 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 B@0.0.1. 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 in package.json. If typescript is locked at 2.4.1 in your package-lock.json, it should remain that way until it is changed. And lets say tomorrow typescript releases version 2.4.2. If I checkout your branch and run npm install, npm will respect the lockfile and install 2.4.1.
关于package-lock.json的更多信息:
package-lock。当NPM修改node_modules树或package.json时,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
也许你应该用这样的东西
npm ci
而不是使用npm install 如果您不想更改包的版本。
根据官方文档,npm install和npm ci都安装了项目所需的依赖项。
主要的区别是,npm install确实使用package来安装包。Json作为引用。在npm ci的情况下,它确实使用package-lock来安装包。Json作为参考,确保每次安装的包都是正确的。
编辑:“锁”这个名字是一个棘手的名字,它的NPM试图赶上Yarn。这不是一个锁定的文件。包中。Json是一个用户固定的文件,一旦“安装”将生成node_modules文件夹树,然后该树将被写入package-lock.json。所以你看,它是另一种方式-依赖版本将从包拉。Json和包锁。Json应该被称为package-tree.json
(希望这能让我的回答更清楚,在这么多的反对票之后)
一个简单的答案:打包。Json像往常一样有你的依赖项,而package-lock。Json是“一个精确的,更重要的是可复制的node_modules树”(取自NPM文档本身)。
至于这个棘手的名字,它的NPM试图赶上Yarn。