package-lock.json
在多人开发时经常冲突,该如何解决才能保证线上质量?package.json
如何定义才能符合我们的预期?
本文通过实验来探究包版本管理最佳实践,测试版本:node v12.20.0 (npm v6.14.8)
文章目录
一、问题
- 什么时候用到
- 什么时候更新
- 正常 npm i 会更新 lock 文件吗
- npm i xxx -S 会更新 lock 文件吗
- 删掉一个包会更新吗
- package.json 锁死后,lock 文件还会更新吗
- lock文件是1.1.0,package.json从^1.0.0 改到 ^1.0.1
- 怎么强制更新
- cnpm、pnpm 影响
二、说明
2.1 package.json 规则
- 如果写入的是 〜0.13.0,则只更新补丁版本:即 0.13.1 可以,但 0.14.0 不可以。
- 如果写入的是 ^0.13.0,则要更新补丁版本和次版本:即 0.13.1、0.14.0、依此类推。
- 如果写入的是 0.13.0,则始终使用确切的版本。
2.2 package-lock.json 作用
npm
版本是5+
,会自动生成package-lock.json
- 简单来说就是锁定安装模块的版本号,例如下图锁定二级依赖项的版本,保证版本稳定
三、实验
3.1 正常新安装
-
我们用
pdfjs-dist
这个包来做测试,目前最新版2.15.349
-
空项目的
package.json
如下
{
"name": "test",
"dependencies": {
}
}
-
安装一个新包
npm i pdfjs-dist -S
-
安装结果,lock 文件为 2.15.349 版本
{
"name": "test",
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"dommatrix": {
"version": "1.0.3",
"resolved": "http://bnpm.byted.org/dommatrix/-/dommatrix-1.0.3.tgz",
"integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww=="
},
"pdfjs-dist": {
"version": "2.15.349",
"resolved": "http://bnpm.byted.org/pdfjs-dist/-/pdfjs-dist-2.15.349.tgz",
"integrity": "sha512-EeCfqj6xi4/aegKNS7Bs+TCg3Y5gmKmG0s/5xXI0PqWW66x+Nm7iFXBpVcup7HnR8sNDm+5NESfFr8T6DeWp9Q==",
"requires": {
"dommatrix": "^1.0.3",
"web-streams-polyfill": "^3.2.1"
}
},
"web-streams-polyfill": {
"version": "3.2.1",
"resolved": "http://bnpm.byted.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
}
}
}
3.2 确定版本
- 我们选取最近两年下载量最高的版本
2.12.313
写死
{
"name": "test",
"dependencies": {
"pdfjs-dist": "2.12.313"
}
}
npm i
安装结果
pdfjs-dist
使用了固定的2.12.313
版本- 竟然没有其他依赖,这可能也是使用量高的原因?
package-lock.json
结果
{
"name": "test",
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"pdfjs-dist": {
"version": "2.12.313",
"resolved": "http://bnpm.byted.org/pdfjs-dist/-/pdfjs-dist-2.12.313.tgz",
"integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA=="
}
}
}
3.3 补丁版本升级
{
"name": "test",
"dependencies": {
"pdfjs-dist": "~2.12.313"
}
}
npm i
安装结果package-lock.json
结果没有变化,因为 lock 文件锁死
npm upate
结果也没有变化,因为 2.12 下面只有 313 一个补丁版本
3.4 次版本升级
{
"name": "test",
"dependencies": {
"pdfjs-dist": "^2.12.313"
}
}
3.4.1 正常安装
npm i
安装结果package-lock.json
因为版本锁死,依然没有变化
3.4.2 强制更新
npm update
更新结果package-lock.json
根据 package.json 更新到最新package.json
也相应的更新
package-lock.json
文件更新结果
{
"name": "test",
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"dommatrix": {
"version": "1.0.3",
"resolved": "http://bnpm.byted.org/dommatrix/-/dommatrix-1.0.3.tgz",
"integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww=="
},
"pdfjs-dist": {
"version": "2.15.349",
"resolved": "http://bnpm.byted.org/pdfjs-dist/-/pdfjs-dist-2.15.349.tgz",
"integrity": "sha512-EeCfqj6xi4/aegKNS7Bs+TCg3Y5gmKmG0s/5xXI0PqWW66x+Nm7iFXBpVcup7HnR8sNDm+5NESfFr8T6DeWp9Q==",
"requires": {
"dommatrix": "^1.0.3",
"web-streams-polyfill": "^3.2.1"
}
},
"web-streams-polyfill": {
"version": "3.2.1",
"resolved": "http://bnpm.byted.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
}
}
}
package.json
文件更新结果
3.4.3 次版本允许更新,并修改补丁版本
- 将
package.json
改为"pdfjs-dist": "^2.12.500"
{
"name": "test",
"dependencies": {
"pdfjs-dist": "^2.12.500"
}
}
npm i
安装结果package.json
无变化package-lock.json
中更新为2.15.349
最新版
这里需要特别注意的是,从确定版本改为次版本更新的时候(2.12.313 => ^2.12.313),是不会更新 lock 文件的;
但是从次版本更新改动补丁版本(^2.12.313 => ^2.12.500),就会触发 lock 更新;
3.5 安装新包
我们探索两种情况下安装新包:
- 确定版本
- 次版本
3.5.1 确定版本安装新包
- 执行命令:
npm i react -S
package.json
文件更新结果:新增一行"react": "^18.2.0"
package-lock.json
文件更新结果:pdfjs-dist
版本不受影响,新增 3 个react
依赖包
{
"name": "test",
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"js-tokens": {
"version": "4.0.0",
"resolved": "http://bnpm.byted.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"loose-envify": {
"version": "1.4.0",
"resolved": "http://bnpm.byted.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"requires": {
"js-tokens": "^3.0.0 || ^4.0.0"
}
},
"pdfjs-dist": {
"version": "2.12.313",
"resolved": "http://bnpm.byted.org/pdfjs-dist/-/pdfjs-dist-2.12.313.tgz",
"integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA=="
},
"react": {
"version": "18.2.0",
"resolved": "http://bnpm.byted.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"requires": {
"loose-envify": "^1.1.0"
}
}
}
}
3.5.2 删除新安装包
package.json
文件删除一行"react": "^18.2.0"
- 执行命令:
npm i
package-lock.json
文件更新结果:pdfjs-dist
版本不受影响,删除 3 个react
依赖包
3.5.3 次版本安装新包
- 初始情况:
package.json
改为次版本更新,但是package-lock.json
文件依然为2.12.313
{
"name": "test",
"dependencies": {
"pdfjs-dist": "^2.12.313"
}
}
- 执行命令:
npm i react -S
package.json
文件更新结果:新增一行"react": "^18.2.0"
{
"name": "test",
"dependencies": {
"pdfjs-dist": "^2.12.313",
"react": "^18.2.0"
}
}
package-lock.json
文件更新结果:同 「3.5.1 确定版本安装新包」,说明 lock 文件锁包的有效性
3.6 cnpm 影响
- 初始状态:
package.json
允许次版本更新"pdfjs-dist": "^2.12.313"
,package-lock
文件写死2.12.313
版本 - 执行命令:
cnpm i
,node_modules
包没有变动 - 执行命令:
rm -rf node_modules/
删除已安装包 - 执行命令:
cnpm i
,node_modules
包更新到2.15.349
最新版本,无视package-lock.json
的锁定同时也不更新该文件
- 执行命令:
npm i
,node_modules
包还原到2.12.313
最新版本,package-lock.json
锁定有效
- 结论:
cnpm
不支持(忽略)依据package-lock.json
文件安装模块,默认依赖package.json
进行安装
四、如何解决冲突
当两个同学都改动了 package.json
的时候,package-lock.json
文件的更新可能达到上千行的冲突,这时候如何处理?
- 方式1:删掉
package-lock.json
,npm i
重新安装?- 这种方式最不可取,相当于 lock 文件完全失效,全部重新安装
- 方式2:手动合并?
- 风险太高,
integrity
字段 sha-512 校验如果改错会导致安装失败
- 风险太高,
- 最佳实践
- 将
package-lock.json
还原到最近一个没有冲突的版本(例如上一版 master),解决package.json
的冲突后(这个手动解决的风险可控),npm i
自动更新 lock 文件
- 将
五、结论
- 持续使用 npm,保证 lock 文件的有效性
- package-lock.json,不能手动修改,不能删除,降低风险
- package.json 锁死版本降低误更新的可能性(同时继续使用 lock 文件,双重保险)
参考文档
- http://nodejs.cn/learn/the-package-lock-json-file
- https://zhuanlan.zhihu.com/p/89093696
- https://stackoverflow.com/questions/44297803/what-is-the-role-of-the-package-lock-json
- https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json