有没有办法修复 package-lock.json 的 lockfileVersion,使得 npm 使用特定的格式?

273
如果在一个使用package-lock.json"lockfileVersion": 1的项目中,两个不同的开发人员分别使用不同版本的node(12/15)和npm(6/7),当使用npm 7x的开发人员安装新软件包时,它似乎会重新创建package-lock.json并使用"lockfileVersion": 2。这会给使用npm v6的开发人员带来问题,因为它尝试处理lockfileVersion 2,但最终会产生新的差异。

npm警告read-shrinkwrap:此npm版本与lockfileVersion@1兼容,但package-lock.json是由lockfileVersion@2生成的。我将尽力而为!

有没有办法指定新版本的npm仅使用"lockfileVersion": 1?或者我们只能让所有开发人员都使用相同版本的npm呢?
9个回答

148

有没有办法指定新版本的 npm 只使用 "lockfileVersion": 1?还是我们只能让所有开发人员使用相同版本的 npm

我建议您锁定Node/NPM版本,并在开发、测试和生产环境中保持一致。

您可以利用 nvm 来管理Node版本,通过在项目中添加.nvmrc文件来实现(别忘了将其存储在源代码控制中)。

例如,.nvmrc 将如下所示:

$ cat .nvmrc
14.15.0

然后,您可以使用nvm install && nvm use来使用固定版本的Node。

NPM还支持engines

您可以指定您的程序适用的Node版本:

{ "engines" : { "node" : ">=0.10.3 <0.12" } }

与依赖项一样,如果不指定版本(或将版本指定为“*”),则任何版本的Node都可以。

如果指定了“engines”字段,则npm将要求“node”在该列表中的某个位置。 如果省略了“engines”,则npm将假定它适用于Node。

您还可以使用“engines”字段来指定哪些版本的npm能够正确安装您的程序。 例如:

{ "engines" : { "npm" : "~1.0.20" } }

除非用户设置了engine-strict配置标志,否则此字段仅是建议性的,并且仅在将您的软件包作为依赖项安装时产生警告。

当利用engines字段并且要求npm在版本约束不满足时失败时,可以在.npmrc文件中设置engine-strict=true(默认情况下为false)或者作为npm_config_engine_strict=true环境变量

如果设置为true,则npm将固执地拒绝安装(甚至考虑安装)任何声明与当前Node.js版本不兼容的软件包。

可以通过设置--force标志来覆盖此设置。

另一种方法是使用Docker容器作为开发和执行的运行环境,这意味着您既不需要安装Node也不需要NPM。例如:

$ mkdir my-project
$ cd my-project
$ docker run --rm -it -v $PWD:/app --entrypoint /bin/bash --workdir /app node:14.15.0
root@4da6ee3c2ac0:/app# npm init -y
Wrote to /app/package.json:

{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}


root@4da6ee3c2ac0:/app# npm install
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN app@1.0.0 No description
npm WARN app@1.0.0 No repository field.

up to date in 1.694s
found 0 vulnerabilities

root@4da6ee3c2ac0:/app# exit
exit
$ ls -x1
package-lock.json
package.json

正如您所看到的,既没有Node,也没有NPM:

  1. 为新项目创建一个新目录
  2. 启动一个Node Docker容器,该容器已安装了Node和NPM
  3. 创建一个新项目(npm init -y
  4. 退出Docker容器
  5. 列出工作目录中容器所在的文件

由于上面的docker run命令很长,您可能希望利用docker-compose进行更简化的工作流程。


2
嘿,我本来希望避免再创建一个 .*rc 文件,但这可能是真正的答案和解决潜在问题的最佳整体解决方案。 - Ben
@Ben:你可以使用docker-compose文件来避免另一个rc文件;)(我已经相应地更新了我的答案) - Mr.
我喜欢使用nvm ls而不是查看rc文件。它可以提供更多关于你拥有哪些版本和哪一个正在运行的信息。这种方法更容易记忆,因为大多数版本管理器都有类似的命令。 - jcollum
1
请注意,如果您使用npm并希望升级npm,则最简单的方法是nvm install-latest-npm - Clément Renaud
这并没有强制使用特定的npm版本。运行nvm install && nvm use(其中.nvmrc包含12),将设置npm为v6,但是一旦在您的笔记本电脑上安装了最新版本的npm(npm install -g npm@latest),它也会更新到您的nvm版本中(nvm use现在返回npm v8),因此您不能确保开发团队之间的一致性。 - manuchaud100
1
@manuchaud100,正如所写的,在 package.json 中的 engine 应该涵盖它。如果不行,我建议改进答案。 - Mr.

118

从版本8.1.0开始,npm有一个标志--lockfile-version,您可以使用它来覆盖默认的锁定文件版本:

npm i --lockfile-version 3

您可以通过添加标志--package-lock-only来更新/生成锁定文件(lock file)而不安装依赖项(dependencies)

npm i --lockfile-version 3 --package-lock-only

这是原始PR链接。


8
未来遇到这个问题的其他人,必须留下“这应该是最佳答案”的评论。 - Tomáš Hübelbauer

66

npm警告read-shrinkwrap,此版本的npm与lockfileVersion@1兼容,但package-lock.json是为lockfileVersion@2生成的。 我会尽力处理它!

要解决此问题,请运行以下命令:

npm i -g npm@latest

全局地运行该命令

npm i npm@latest

在项目文件中帮助我解决了这个问题。


你是在 Linux 系统中完成的吗? - AllisLove
不,这在Windows 10中不行。 - S J BHAVANA
1
好的,谢谢。我刚刚重新启动了我的操作系统,现在一切正常。 - AllisLove
3
这个 npm i -g npm@latest 对我有用。谢谢。 - Arif Shaikh
1
在我的Windows 10上,我运行了“npm i -g npm@latest”,并且还必须安装最新版本的nodeJS(16.13.0)。 - linos
对于大多数用例,如果要本地安装而非全局安装,请将npm i npm@latest -D作为开发依赖项进行安装。 - Hoppe

25
据我所见,npm文档显示,尽管有警告,但npm v6可以使用版本2的锁定文件,因此您不需要执行已接受的答案中建议的任何操作,可以安全地忽略警告消息。
npm 7发行说明中,他们说:
引起注意的一个变化是新的锁定文件格式,该格式向后兼容npm 6用户。 lockfile v2解锁了进行确定性和可重复构建以产生软件包树的能力。
npm文档中,它说(我强调): lockfileVersion 一个整数版本,从1开始,表示用于生成此package-lock.json时使用了本文档的版本号的语义。 请注意,npm v7中的文件格式发生了重大更改,以跟踪否则需要查看node_modules或npm注册表的信息。由npm v7生成的锁定文件将包含lockfileVersion:2。 - 没有提供版本:来自npm v5之前版本的“古老”收缩包文件。 - 1:由npm v5和v6使用的锁定文件版本。 - 2:由npm v7使用的锁定文件版本,向后兼容v1锁定文件。
  • 3:npm v7所使用的锁定文件版本,没有向后兼容性。该版本用于node_modules/.package-lock.json中的隐藏锁定文件,并且在不久的将来,一旦npm v6的支持不再相关,可能会被npm的未来版本所使用
  • 这就是为什么它们可以自动将锁定文件从v1升级到v2(您提到的),而不会破坏任何东西。


    15
    我们看到的是,任何仍使用npm 6并在该项目中运行“npm install”的人最终会发现package-lock将其自身设置回lockfileversion 1。这真的很恼人,因为我们已经使用npm 7更新了它至版本2。我们不得不尝试其中一个解决方案,或者让一群开发者及时更新他们的机器...哈哈。 - Jeremy L
    没有意识到npm 6会适当降级它。在package.json中,我们有“engines”:{..}来锁定node/npm范围。某些标志允许npm忽略此项并仍然升级到lockfileVersion:2。最好保持npm和node版本同步。谢谢Jeremy! - TamusJRoyce
    @JeremyL 在 .npmrc 中禁用 package-lock.json,使用 package-lock=false,然后每次更新依赖时手动运行 npm shrinkwrap - Miles B Huff

    10

    相比使用nvm,有一种简单得多的解决方案:

    npx npm@6.14.17 i --save
    

    使用此方法,您可以生成一个版本为 1 的新锁定文件,使用最新的 Node.js 版本,而不需要更改计算机上的任何内容。


    你说得对。这是更简单的解决方案!使用npx来执行任务,不用担心本地包版本。谢谢! - Jose Miguel Ochoa

    6
    我今天遇到了同样的问题。我正在与一个使用不同版本的npm(>7)的开发者一起工作,我也遇到了同样的问题。我只需升级我的npm版本为其他开发者所使用的最新版本即可解决该问题。 以下是升级您的npm(适用于Windows)的步骤:
    首先,请确保您可以通过以提升的PowerShell运行以下命令来在系统上执行脚本。要将PowerShell作为管理员运行,请单击开始,搜索PowerShell,右键单击PowerShell并选择以管理员身份运行
    接下来执行以下命令:
    Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
    

    然后,要安装和使用此升级工具,请运行以下命令(也可以从提升的 PowerShellcmd.exe 中运行)。注意:此工具需要至少 Node v8

    npm install --global --production npm-windows-upgrade
    npm-windows-upgrade
    

    想要只安装最新版本?当然:

    npm-windows-upgrade --npm-version latest
    

    现在您可以通过命令行选择要安装的版本。

    https://github.com/felixrieseberg/npm-windows-upgrade

    上面的链接是我使用过的工具,这个工具适用于Linux/Windows操作系统。希望它能对你有所帮助。


    0

    锁定文件的构建取决于npm版本。v7+将创建锁定文件2,而以下版本将创建锁定文件v1。

    锁定文件v2向后兼容,因此运行npm < v6的人可以使用它,但是我正在我的第二个屏幕上查看circleci构建失败,这表明我们使用的一些npm包与锁定文件v2不兼容...即旧的npm包可能没有得到很好的维护和与锁定文件v2的兼容性。

    因此,最好的做法可能是将您的环境docker化并隔离。

    这就是为什么docker被发明出来的原因!在docker容器中运行您的项目,然后有一个makefile命令来构建您的项目,可能类似于

    .PHONY: up
    up:
        $(MAKE) down
        docker-compose up -d
        $(MAKE) logs
    

    使用组合文件来设置项目,然后依赖于“make <插入命令>”来运行/构建项目。一个命令可能是“make shell”,以进入一个 shell 环境,在这个环境中所有的开发人员都有相同的 npm / node 版本。“npm i -g npm@latest” 不是一个答案,因为它只是在它运行的位置上安装 npm,所以新的开发人员仍然需要运行该命令,除非它是构建的一部分。

    0

    -4
    尝试删除 package-lock.json 文件,然后再次运行 npm install

    这与重新生成锁定文件无关,而与安装的NPM版本有关。您可以使用旧版本的NPM生成文件100次,但不会有任何区别。 - Hafiz Temuri

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接