package-lock.json的作用
由于package.json
文件中的语义版本锁定,安装源也不固定,我们在协同开发和线上构建时,不同开发者npm i
得到的依赖版本可能会有一定差异。而package-lock.json
的出现,正是为了保证我们依赖版本的一致性。
对于是否将package-lock.json
文件上传到远程仓库,也有许多有趣的讨论,例如package-lock.json 需要写进 .gitignore 吗?
这里讨论的是将该文件上传到远程仓库时,可能遇到的一些问题和解决方法。
package-lock.json的表现
在npm@5.4.2版本后的表现:
-
无package-lock.json
npm i
根据package.json进行安装,并生成package-lock.json -
package.json和package-lock.json的版本不兼容
npm i
会以package.json为准进行安装,并更新package-lock.json -
package.json和package-lock.json的版本兼容
npm i
会以package-lock.json为准进行安装。
关于旧的npm版本的表现,这个回答有比较清楚的解释。
更多特性,也可参考package-lock npm官方文档的相关说明。
npm ci
由于以上1、2点的存在,即使有package-lock.json文件,配合npm i
,我们也不能保证线上构建
时的依赖版本与本地开发
时的一致。
npm ci
是类似于npm i
的命令,适用于ci时安装依赖。npm ci
与npm i
主要的差异有:
- 使用
npm ci
的项目必须存在package-lock.json或npm-shrinkwrap.json文件,否则无法执行(即以上1的情况) - 如果package-lock.json或npm-shrinkwrap.json中的依赖与package.json中不一致(即以上2的情况),
npm ci
会报错并退出,而不是更新lock文件 npm ci
只会安装整个项目,无法单独安装某个依赖项目- 如果项目中已有
node_modules
,该文件夹会在npm ci
执行安装前自动被移除 - 该命令不会写入package.json或lock文件,安装的行为是完全被固定的。
基于以上几种特性,使用npm ci
能够有效防止线上构建的依赖与开发者本地不一致。
可查阅npm文档
如何解决package-lock.json的冲突
package-lock.json文件不由开发者自行写入,在协同开发时,某一方若更新了依赖,很容易产生大量冲突,且难以逐个解决。
-
npm文档中推荐的两种方式:
- 从5.7.0版本的npm开始,解决package-lock.json的冲突可以通过解决package.json的冲突后,运行
npm install [--package-lock-only]
来完成。npm会自动解析package-lock.json中的冲突,并生成一个有着合理的tree结构,且包含了两个分支的所有依赖的lock文件。 - 文档中还提到了一个npm-merge-driver工具,可以帮助开发者解决package-lock.json的冲突。
- 从5.7.0版本的npm开始,解决package-lock.json的冲突可以通过解决package.json的冲突后,运行
-
至于旧版本的npm,可以尝试对于package-lock.json文件,忽略掉冲突,并重新
npm i
。以下是一些可行的具体操作。- 在vscode上选择Accept All Incoming/Current Changes后
npm i
。 - 将package-lock.json文件checkout到之前某个commit的状态,
git checkout [commitId] -- path/to/package-lock.json
,再npm i
最好将文件重置到非自己开发分支的状态,便于合并之后的验证。例如,对于将master合进自己开发的特性分支的情况(如
git pull origin master
),对于冲突,选择Accept All Incoming。 - 在vscode上选择Accept All Incoming/Current Changes后