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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45022048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 18:21:22  来源:igfitidea点击:

Why does "npm install" rewrite package-lock.json?

node.jsnpmnpm-installpackage-lock.json

提问by Viper Bailey

I just recently upgraded to npm@5. I now have a package-lock.jsonfile with everything from package.json. I would expect that, when I run npm installthat the dependency versions would be pulled from the lock file to determine what should be installed in my node_modulesdirectory. What's strange is that it actually ends up modifying and rewriting my package-lock.jsonfile.

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

For example, the lock file had typescript specified to be at version 2.1.6. Then, after the npm installcommand, the version was changed to 2.4.1. That seems to defeat the whole purpose of a lock file.

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

What am I missing? How do I get npm to actually respect my lock file?

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

采纳答案by jotaen

Update 3:As other answers point out as well, the npm cicommand got introduced in npm 5.7.0 as additional way to achieve fast and reproducible builds in the CI context. See the documentationand npm blogfor further information.

更新 3:正如其他答案所指出的那样,该npm ci命令在 npm 5.7.0 中被引入,作为在 CI 上下文中实现快速和可重复构建的额外方法。有关更多信息,请参阅文档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.jsonwas changed in npm 5.1.0as discussed in issue #16866. The behaviour that you observe is apparently intended by npm as of version 5.1.0.

原始答案:的行为package-lock.json已在npm 5.1.0中更改,如问题 #16866 中所述。您观察到的行为显然是 npm 从 5.1.0 版开始的。

That means that package.jsoncan override package-lock.jsonwhenever a newer version is found for a dependency in package.json. If you want to pin your dependencies effectively, you now must specify the versions without a prefix, e.g., you need to write them as 1.2.0instead of ~1.2.0or ^1.2.0. Then the combination of package.jsonand package-lock.jsonwill yield reproducible builds. To be clear: package-lock.jsonalone no longer locks the root level dependencies!

认为它的意思package.json可以覆盖package-lock.json每当有新版本时发现的依赖package.json。如果您想有效地固定您的依赖项,您现在必须指定不带前缀的版本,例如,您需要将它们编写为1.2.0而不是~1.2.0or ^1.2.0。然后结合package.jsonpackage-lock.json将产生可重现的构建。需要明确的是: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. (In my eyes it is a questionable decision; at least the name lockdoesn't hold true any longer.)

这个设计决定是否好是有争议的,由于这种混淆在 GitHub 上的issue #17979上有一个持续的讨论。(在我看来,这是一个有问题的决定;至少这个名字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. See this documentation of package locksfor further explanation.

另一个注意事项:对于不支持不可变包的注册表也有限制,例如当您直接从 GitHub 而不是 npmjs.org 拉取包时。有关进一步说明,请参阅此包锁文档

回答by Ivan Shcherbakov

I've found that there will be a new version of npm 5.7.1with the new command npm ci, that will install from package-lock.jsononly

我发现会有一个带有新命令的新版本的 npm 5.7.1npm ci,它将package-lock.json仅从安装

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.

新的 npm ci 命令仅从您的锁定文件安装。如果你的 package.json 和你的锁文件不同步,那么它会报告一个错误。

它的工作原理是扔掉你的 node_modules 并从头开始重新创建它。

除了保证您只会获得锁定文件中的内容之外,当您不从 node_modules 开始时,它也比 npm install 快得多(2x-10x!)。

正如您可能从名称中了解到的那样,我们希望它对持续集成环境有很大的帮助。我们还希望从 git 标签进行生产部署的人会看到重大收益。

回答by Gal Margalit

Use the newly introduced

使用新推出的

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.

npm ci 承诺对大型团队最大的好处。让开发人员能够“签署”一个包锁可以促进大型团队之间更有效的协作,并且能够准确安装锁文件中的内容有可能每月节省数十甚至数百个开发人员小时,从而释放团队花更多的时间来构建和运送令人惊奇的东西。

Introducing npm cifor faster, more reliable builds

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

回答by Ahmad Abdelghany

Short Answer:

简答:

  • npm installhonors package-lock.json only if it satisfies the requirements of package.json.
  • If it doesn't satisfy those requirements, packages are updated & package-lock is overwritten.
  • If you rather fail the build, than rewrite package-lock when that happens, use npm ci.
  • npm install仅当 package-lock.json 满足 package.json 的要求时才使用它。
  • 如果它不满足这些要求,则更新包并覆盖包锁。
  • 如果您宁愿让构建失败,也不愿在发生这种情况时重写 package-lock,请使用npm ci.


Here is a scenario that might explain things (Verified with NPM 6.3.0)

这是一个可以解释事情的场景(已通过 NPM 6.3.0 验证)

You declare a dependency in package.json like:

您在 package.json 中声明一个依赖项,例如:

"depA": "^1.0.0"

Then you do, npm installwhich will generate a package-lock.json with:

然后你做,npm install这将生成一个 package-lock.json :

"depA": "1.0.0"

Few days later, a newer minor version of "depA" is released, say "1.1.0", then the following holds true:

几天后,发布了一个更新的“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)

Next, you manually update your package.json to:

接下来,您手动将 package.json 更新为:

"depA": "^1.1.0"

Then rerun:

然后重新运行:

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)

回答by Daniel Tonon

Use the npm cicommand instead of npm install.

使用npm ci命令而不是npm install.

"ci" stands for "continuous integration".

“ci”代表“持续集成”。

It will install the project dependencies based on the package-lock.json file instead of the lenient package.json file dependencies.

它将安装基于 package-lock.json 文件而不是 lenient package.json 文件依赖项的项目依赖项。

It will produce identical builds to your team mates and it is also much faster.

它将为您的队友生成相同的构建,而且速度也快得多。

You can read more about it in this blog post: https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable

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

回答by Daniel Tonon

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. There was a cross platform bug in 5.4.2 that was causing the issue to still occur.

实际上已在 5.6.0 中修复。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 ciis the command you should be using when installing existing projects now.

npm ci是您现在安装现有项目时应该使用的命令。

回答by Timothy Higinbottom

In the future, you will be able to use a --from-lock-file(or similar) flag to install onlyfrom the package-lock.jsonwithout 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/18286for tracking of the feature.

有关该功能的跟踪,请参阅https://github.com/npm/npm/issues/18286

回答by Matt

You probably have something like:

你可能有这样的事情:

"typescript":"~2.1.6"

in your package.jsonwhich npm updates to the latest minor version, in your case being 2.4.1

在您的package.json哪个 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.1requires 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.1but widgethas been updated to widget v1.0.1. Now your node module are out of sync. This is what package-lock.jsonprevents.

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 的问题

但这并不能解释为什么“npm install”会更改锁定文件。锁定文件不是用于创建可重现的构建吗?如果是这样,无论 semver 值如何,它仍应使用相同的 2.1.6 版本。

回答:

这旨在锁定您的完整依赖树。假设typescript v2.4.1需要widget ~v1.0.0。当您 npm install 时,它会抓取widget v1.0.0. 稍后,您的开发人员(或 CI 构建)执行 npm 安装并获取typescript v2.4.1widget已更新为widget v1.0.1. 现在您的节点模块不同步。这就是package-lock.json防止。

或更一般地说:

例如,考虑

套餐一:

{ "name": "A", "version": "0.1.0", "dependencies": { "B": "<0.1.0" } }

套餐B:

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

和包C:

{“名称”:“C”,“版本”:“0.0.1”}

如果这些是注册表中唯一可用的 A、B 和 C 版本,则正常的 npm install A 将安装:

[email protected] -- [email protected] -- [email protected]

但是,如果发布了 [email protected],则将安装新的 npm install A:

[email protected] -- [email protected] -- [email protected] 假设新版本没有修改 B 的依赖项。当然,新版本的 B 可以包含新版本的 C 和任意数量的新依赖项。如果此类更改不受欢迎,A 的作者可以指定对 [email protected] 的依赖。但是,如果 A 的作者和 B 的作者不是同一个人,则 A 的作者无法在 B 根本没有改变的情况下说他或她不想引入 C 的新发布版本。



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 typescriptis locked at 2.4.1in your package-lock.json, it should remain that way until it is changed. And lets say tomorrow typescriptreleases version 2.4.2. If I checkout your branch and run npm install, npm will respect the lockfile and install 2.4.1.

OP 问题 2:让我看看我是否理解正确。你说的是lock文件指定了二级依赖的版本,但是还是依赖package.json的模糊匹配来确定顶级依赖。那是准确的吗?

答:不可以。 package-lock 锁定整个包树,包括 中描述的根包package.json。如果typescript锁定2.4.1在您的 中package-lock.json,则应保持这种状态,直到更改为止。让我们说明天typescript发布版本2.4.2。如果我检出您的分支并运行npm install,npm 将尊重锁定文件并安装2.4.1.

More on 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. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.

package-lock.json 会为任何 npm 修改 node_modules 树或 package.json 的操作自动生成。它描述了生成的确切树,以便后续安装能够生成相同的树,而不管中间依赖项更新如何。

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.

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.

描述依赖树的单一表示,以便保证团队成员、部署和持续集成安装完全相同的依赖关系。

为用户提供一种“时间旅行”到 node_modules 以前状态的工具,而无需提交目录本身。

通过可读的源代码控制差异来促进树更改的更大可见性。

并通过允许 npm 跳过先前安装的包的重复元数据解析来优化安装过程。

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

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

回答by Sengottaian Karthik

Probably you should use something like this

可能你应该使用这样的东西

npm ci

Instead of using npm installif you don't want to change the version of your package.

npm install如果您不想更改包的版本,则不要使用。

According to the official documentation, both npm installand npm ciinstall the dependencies which are needed for the project.

根据官方文档,npm installnpm ci安装项目所需的依赖项。

The main difference is, npm installdoes install the packages taking packge.jsonas a reference. Where in the case of npm ci, it does install the packages taking package-lock.jsonas a reference, making sure every time the exact package is installed.

主要区别在于,npm install是否安装了packge.json作为参考的软件包。在 的情况下npm ci,它确实安装了package-lock.json作为参考的包,确保每次安装准确的包。

回答by hrdwdmrbl

There is an open issue for this on their github page: https://github.com/npm/npm/issues/18712

在他们的 github 页面上有一个未解决的问题:https: //github.com/npm/npm/issues/18712

This issue is most severe when developers are using different operating systems.

当开发人员使用不同的操作系统时,这个问题最为严重。