我最近刚升级到npm@5。我现在有一个包锁。包含package.json中的所有内容的Json文件。我希望,当我运行npm install时,依赖版本将从锁文件中提取,以确定应该在我的node_modules目录中安装什么。奇怪的是,它实际上最终修改和重写了我的包锁。json文件。

例如,锁文件的typescript被指定为2.1.6版本。然后,在执行npm install命令后,版本被更改为2.4.1。这似乎违背了锁文件的全部目的。

我错过了什么?我如何让npm尊重我的锁文件?


当前回答

使用新引进的

npm ci

NPM ci承诺为大型团队带来最大的好处。让开发人员能够在包锁上“签名”,从而促进大型团队之间更有效的协作,并且能够准确地安装锁文件中的内容,每个月可以为开发人员节省数十个小时(如果不是数百个小时的话),将团队解放出来,花更多时间构建和发布令人惊叹的东西。

引入npm ci以实现更快、更可靠的构建

其他回答

你可能会遇到这样的情况:

"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。

ci代表clean install。

它将基于包锁安装项目依赖项。Json文件,而不是宽大的包。Json文件依赖关系。

它将生成与团队成员相同的构建,并且速度更快。

你可以在这篇博客文章中阅读更多信息: https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable

Npm install检测对包的任何更改。Json文件,以反映相应的依赖列表。

例:如果用户添加或删除了一个新的依赖项,构建将下载或删除本地计算机中的依赖项。我们可以将其与java中的.m2存储库进行比较,其中maven会不断跟踪pom.xml文件以更新依赖项。

package-lock。Json是package的副本。Json在运行时被内部进程使用,唯一的区别是包锁。Json对用户来说是只读的。

更新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提取包时。有关进一步的解释,请参阅包锁的文档。

编辑:“锁”这个名字是一个棘手的名字,它的NPM试图赶上Yarn。这不是一个锁定的文件。包中。Json是一个用户固定的文件,一旦“安装”将生成node_modules文件夹树,然后该树将被写入package-lock.json。所以你看,它是另一种方式-依赖版本将从包拉。Json和包锁。Json应该被称为package-tree.json

(希望这能让我的回答更清楚,在这么多的反对票之后)


一个简单的答案:打包。Json像往常一样有你的依赖项,而package-lock。Json是“一个精确的,更重要的是可复制的node_modules树”(取自NPM文档本身)。

至于这个棘手的名字,它的NPM试图赶上Yarn。