大部分时候我们都不会去关注package-lock.json这个文件,因为大部分时候我们都不需要去关注自己使用的库的版本,因为这个原因,读者一般也不需要阅读本文。当我们对需要使用的库有明确的版本要求,或者自己写了一个库,在测试的时候需要知道自己测的是哪一版,这个时候就需要注意package-lock.json了。
以下我们通过一些实际试验来了解package-lock.json,相关代码:github.com/covbond/pac….
package-lock.json是如何生成的?
命令行切换到create-lock中,执行:
npm i lodash
执行的结果是package.json中dependencies增加了lodash字段,通常是最新版本,在我试验的时候,它是4.17.15:
{
"name": "create-lock",
"version": "1.0.0",
"description": "create package-lock.json",
"main": "index.js",
"scripts": {},
"author": "covbond",
"license": "MIT",
"dependencies": {
+ "lodash": "^4.17.15"
}
}
此外,还生成了package-lock.json文件:
{
"name": "create-lock",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
}
}
}
我们注意到package.json中lodash版本前面多了一个^,它表示:以后如果有人把这个项目拉下来安装的话,给他安装的版本要和4.17.15兼容,具体来说就是新安装的版本范围是:>= 4.17.15 且 < 5.0.0。需要了解更多的话,可以搜索“npm 语义化版本”。
现在的问题是,如果别人使用你的项目的时候,lodash已经出到4.18.0了,那么当他把项目代码拉下来,执行npm install的时候,最终安装的lodash会是哪个版本呢?是4.18.0还是4.17.15?
这和你上传代码文件的时候有没有上传package-lock.json是有关的。
由于在写这篇文章的时候,lodash版本还没有出到4.18.0,为了得到问题的答案,我们可以将lodash的版本设置为^4.0.0,这是因为这两种情况是类似的,我们可以从^4.0.0的情况推测^4.17.15的情况。
在without-lock文件夹下我们准备了一份package.json文件,其中lodash的版本为^4.0.0。将命令行切换到这个文件夹下,执行npm install,我们会发现,最终安装的版本不是4.0.0,而是当前最新的lodash版本,这是符合预期的。
但是,如果加上package-lock.json文件,最终安装的lodash版本会是怎样的呢?
使用lock文件
在with-lock文件夹中,我们额外准备了一个lock文件(package-lock.json名字太长,我们用lock指代它),其中lodash的版本是4.0.0。
我们在这个文件夹下执行npm install后,会发现node_modules中lodash的版本是4.0.0。
经过这两个例子的对比,我们就会发现,看起来好像是:如果有lock文件,那么最终版本由lock文件中的版本决定,否则是由package.json中的语义化版本决定的。
那么是不是可以说有lock就只用看lock,没lock就看package.json呢?
其实不是这样的,我们可以再做一个试验。
手动修改package.json会怎样?
有时候我们想更新一个库,就直接编辑package.json文件改版本,然后跑npm install。这样的话,最后安装的版本是怎样确定的呢?
切换到modify-package-1,准备的package.json文件中已经将lodash的版本手动从^4.17.15改成了^4.0.0, 这就相当于我们手动修改了lodash的版本,执行npm install,然后我们会发现lock文件一点变化也没有。最终安装的版本还是4.17.15。
切换到modify-package-2,这次准备的package.json文件中版本我们手动改成了^3.0.0。如果执行npm install,最终会安装什么样的版本呢?
从上一部分得到的结论来推测,我们有lock文件,应该全部都听lock的,即使package.json中版本是^3.0.0(>= 3.0.0 且 < 4.0.0),也不用管。
可是,当执行npm install后,我们发现,最终安装的版本是3.10.1(它是满足范围要求的最后一个版本,在lodash中可以查看这个库的历史版本)。而且lock文件被修改了:
{
"name": "test-lock",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
}
}
}
从这个例子中我们可以看出,最终结论应该是:对一个库来说,package.json中说要这个版本,lock中说要那个版本,如果没冲突的话,就全听lock的,否则听package.json的,而且还会更新lock文件。
参考资料
这篇文章受But what the hell is package-lock.json?启发而写成。
运行环境
- node: v12.16.1
- npm: 6.13.4