当前位置: 首页 > 工具软件 > npm-consider > 使用案例 >

为什么“ npm install”会重写package-lock.json?

鲁光霁
2023-12-01

本文翻译自:Why does “npm install” rewrite package-lock.json?

I just recently upgraded to npm@5. 我最近才升级到npm @ 5。 I now have a package-lock.json file with everything from package.json. 我现在有一个package-lock.json文件,其中包含package.json中的所有内容。 I would expect that, when I run npm install that the dependency versions would be pulled from the lock file to determine what should be installed in my node_modules directory. 我希望当我运行npm install ,将从锁定文件中提取依赖项版本,以确定应该在我的node_modules目录中安装什么。 What's strange is that it actually ends up modifying and rewriting my package-lock.json file. 奇怪的是,它实际上最终修改并重写了package-lock.json文件。

For example, the lock file had typescript specified to be at version 2.1.6. 例如,锁定文件的打字稿指定为版本2.1.6。 Then, after the npm install command, the version was changed to 2.4.1. 然后,在npm install命令之后,版本更改为2.4.1。 That seems to defeat the whole purpose of a lock file. 这似乎破坏了锁定文件的全部目的。

What am I missing? 我想念什么? How do I get npm to actually respect my lock file? 如何让npm真正尊重我的锁定文件?


#1楼

参考:https://stackoom.com/question/32uI4/为什么-npm-install-会重写package-lock-json


#2楼

You probably have something like: 您可能有类似以下内容:

"typescript":"~2.1.6"

in your package.json which npm updates to the latest minor version, in your case being 2.4.1 在您的package.json ,其中npm更新为最新的次要版本,在您的情况下为2.4.1

Edit: Question from OP 编辑:OP的问题

But that doesn't explain why "npm install" would change the lock file. 但这并不能解释为什么“ npm install”会更改锁定文件。 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. 如果是这样,则无论semver值如何,都应仍使用相同的2.1.6版本。

Answer: 回答:

This is intended to lock down your full dependency tree. 这旨在锁定您的完整依赖关系树。 Let's say typescript v2.4.1 requires widget ~v1.0.0 . 假设typescript v2.4.1需要widget ~v1.0.0 typescript v2.4.1 When you npm install it grabs widget v1.0.0 . 当您安装npm时,它会获取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 . 稍后在您的其他开发人员(或CI构建)上进行npm安装并获取typescript v2.4.1widget已更新为widget v1.0.1 Now your node module are out of sync. 现在,您的节点模块不同步。 This is what package-lock.json prevents. 这就是package-lock.json防止的。

Or more generally: 或更笼统地说:

As an example, consider 例如,考虑

package A: 套餐A:

{ "name": "A", "version": "0.1.0", "dependencies": { "B": "<0.1.0" } } {“名称”:“ A”,“版本”:“ 0.1.0”,“依赖关系”:{“ B”:“ <0.1.0”}}

package B: 套餐B:

{ "name": "B", "version": "0.0.1", "dependencies": { "C": "<0.1.0" } } {“ name”:“ B”,“ version”:“ 0.0.1”,“ dependencies”:{“ C”:“ <0.1.0”}}

and package C: 和包C:

{ "name": "C", "version": "0.0.1" } {“ 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,B和C的唯一版本,则将安装普通的npm install A:

A@0.1.0 -- B@0.0.1 -- C@0.0.1 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: 但是,如果发布了B@0.0.2,则将安装新的npm install A:

A@0.1.0 -- B@0.0.2 -- C@0.0.1 assuming the new version did not modify B's dependencies. A@0.1.0-B@0.0.2-C@0.0.1假设新版本未修改B的依赖关系。 Of course, the new version of B could include a new version of C and any number of new dependencies. 当然,新版本的B可以包括新版本的C和任何数量的新依赖项。 If such changes are undesirable, the author of A could specify a dependency on B@0.0.1. 如果不希望发生此类更改,则A的作者可以指定对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. 但是,如果A的作者和B的作者不是同一个人,则A的作者无法说当B完全没有变化时,他或她就不想插入新发布的C版本。


OP Question 2: So let me see if I understand correctly. OP问题2:所以让我看看我是否理解正确。 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. 您要说的是,锁定文件指定了二级依赖关系的版本,但仍依赖于package.json的模糊匹配来确定顶级依赖关系。 Is that accurate? 准确吗?

Answer: No. package-lock locks the entire package tree, including the root packages described in package.json . 答:不。package-lock锁定整个软件包树,包括package.json描述的根软件包。 If typescript is locked at 2.4.1 in your package-lock.json , it should remain that way until it is changed. 如果typescript在锁定2.4.1在您的package-lock.json ,直到它被改变了它应该保持这种方式。 And lets say tomorrow typescript releases version 2.4.2 . 并说明天typescript发布2.4.2版本。 If I checkout your branch and run npm install , npm will respect the lockfile and install 2.4.1 . 如果我签出您的分支并运行npm install ,则npm将遵守锁定文件并安装2.4.1

More on package-lock.json : 有关package-lock.json更多package-lock.json

package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. 对于npm修改node_modules树或package.json的任何操作,都会自动生成package-lock.json。 It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates. 它描述了生成的确切树,因此无论中间依赖项更新如何,后续安装都可以生成相同的树。

This file is intended to be committed into source repositories, and serves various purposes: 该文件旨在提交到源存储库中,并具有多种用途:

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. 为用户提供一种工具,使其可以“时间旅行”到node_modules的先前状态,而不必提交目录本身。

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. 并允许npm跳过先前安装的软件包的重复元数据解析,从而优化安装过程。

https://docs.npmjs.com/files/package-lock.json https://docs.npmjs.com/files/package-lock.json


#3楼

Update 3: As other answers point out as well, the npm ci command got introduced in npm 5.7.0 as additional way to achieve fast and reproducible builds in the CI context. 更新3:正如其他答案所指出的那样,npm 5.7.0中引入了npm ci命令,作为在CI上下文中实现快速且可复制的构建的其他方法。 See the documentation and npm blog for further information. 有关更多信息,请参见文档npm博客


Update 2: The issue to update and clarify the documentation is GitHub issue #18103 . 更新2:更新和澄清文档的问题GitHub问题#18103


Update 1: The behaviour that was described below got fixed in npm 5.4.2: the currently intended behaviour is outlined in GitHub issue #17979 . 更新1:以下描述的行为已在npm 5.4.2中修复: GitHub问题#17979中概述了当前预期的行为。


Original answer: The behaviour of package-lock.json was changed in npm 5.1.0 as discussed in issue #16866 . 原始答案: package-lock.json的行为已在问题#16866中npm 5.1.0更改 The behaviour that you observe is apparently intended by npm as of version 5.1.0. 从5.1.0版开始,您观察到的行为显然是npm预期的。

That means that package.json can override package-lock.json whenever a newer version is found for a dependency in package.json . 这意味着,只要在package.json找到依赖项的较新版本, package.json就可以覆盖package-lock.json If you want to pin your dependencies effectively, you now must specify the versions without a prefix, eg, you need to write them as 1.2.0 instead of ~1.2.0 or ^1.2.0 . 如果要有效固定依赖项,则现在必须指定不带前缀的版本,例如,您需要将它们写为1.2.0而不是~1.2.0^1.2.0 Then the combination of package.json and package-lock.json will yield reproducible builds. 然后, package.jsonpackage-lock.json的组合将产生可复制的构建。 To be clear: package-lock.json alone no longer locks the root level dependencies! 需要明确的是:仅package-lock.json不再锁定根级别依赖项!

Whether this design decision was good or not is arguable, there is an ongoing discussion resulting from this confusion on GitHub in issue #17979 . 不管这个设计决定是好的还是不可行的,在GitHub上的问题#17979上一直在进行讨论。 (In my eyes it is a questionable decision; at least the name lock doesn't hold true any longer.) (在我看来,这是一个值得商decision的决定;至少名称lock不再适用。)

One more side note: there is also a restriction for registries that don't support immutable packages, such as when you pull packages directly from GitHub instead of npmjs.org. 还有一点注意事项:对于不支持不可变软件包的注册表也有一个限制,例如当您直接从GitHub而不是npmjs.org提取软件包时。 See this documentation of package locks for further explanation. 有关进一步的说明,请参阅此包锁文档


#4楼

It appears this issue is fixed in npm v5.4.2 看来此问题已在npm v5.4.2中修复

https://github.com/npm/npm/issues/17979 https://github.com/npm/npm/issues/17979

(Scroll down to the last comment in the thread) (向下滚动到线程中的最后一条注释)

Update 更新资料

Actually fixed in 5.6.0. 实际在5.6.0中已修复。 There was a cross platform bug in 5.4.2 that was causing the issue to still occur. 5.4.2中存在一个跨平台错误,导致该问题仍然存在。

https://github.com/npm/npm/issues/18712 https://github.com/npm/npm/issues/18712

Update 2 更新2

See my answer here: https://stackoverflow.com/a/53680257/1611058 在这里查看我的答案: https : //stackoverflow.com/a/53680257/1611058

npm ci is the command you should be using when installing existing projects now. npm ci是您现在安装现有项目时应使用的命令。


#5楼

In the future, you will be able to use a --from-lock-file (or similar) flag to install only from the package-lock.json without modifying it. 将来,您将能够使用--from-lock-file (或类似的)标志仅从 package-lock.json安装而不进行修改。

This will be useful for CI, etc. environments where reproducible builds are important. 这对于CI等可重现构建很重要的环境很有用。

See https://github.com/npm/npm/issues/18286 for tracking of the feature. 请参阅https://github.com/npm/npm/issues/18286以跟踪功能。


#6楼

EDIT: the name "lock" is a tricky one, its NPM trying to catch up with Yarn. 编辑:名称“锁”是一个棘手的人,其NPM试图赶上纱线。 It isn't a locked file whatsoever. 它不是一个锁定的文件。 package.json is a user-fixed file, that once "installed" will generate node_modules folder tree and that tree will then be written in package-lock.json . package.json是用户固定的文件,一旦“安装”,它将生成node_modules文件夹树,然后将该树写入package-lock.json So you see, its the other way around - dependency versions will be pulled from package.json as always, and package-lock.json should be called package-tree.json 因此,您可以看到相反的情况-依赖版本将一如既往地从package.json提取,并且package-lock.json应该称为package-tree.json

(hope this made my answer clearer, after so many downvotes) (希望经过这么多次否决之后,我的回答才能更加清晰)


A simplistic answer: package.json have your dependencies as usual, while package-lock.json is "an exact, and more importantly reproducible node_modules tree" (taken from npm docs itself ). 一个简单的答案: package.json像往常一样具有依赖性,而package-lock.json是“精确的,更重要的是可重现的node_modules树”(取自npm docs本身 )。

As for the tricky name, its NPM trying to catch up with Yarn. 至于棘手的名字,它的NPM试图赶上纱。

 类似资料: