目前的前端现代工程化中,npm
的生态已经成为密不可分的一环,而每个基于 npm
包的项目的 npm init
之后,都会有一个 package.json
,在 npm install
之后又会有一个 package-lock.json
,它们极为相似的名称让我很感兴趣,package-lock.json
究竟是何方神圣?毕竟平常我只修改 package.json
什么?你问我为什么不直接“操作” package-lock.json
?
这么长的文件,我看都不想看/(ㄒoㄒ)/~~
简介
关于 package-lock.json
的介绍比较权威的可以参考 npm Docs
的 package-lock.json
对于基于
npm
修改node_modules
树或者package.json
的任何操作,都会自动生成package-lock.json
。它描述了生成的确切树,以便后续安装能够生成相同的树,而不考虑中间的依赖关系更新。 此文件旨在提交到源存储库中,并用于各种目的:
- 描述依赖关系树的单一表示,以确保队友、部署和持续集成能够安装完全相同的依赖关系。
- 为用户提供一种工具,让他们“时间旅行”到node_module的先前状态,而不必提交目录本身。
- 通过可读的源代码控制差异,提高树更改的可见性。
- 通过允许npm跳过先前安装的包的重复元数据解析,优化安装过程。
- 从npm v7开始,锁定文件包含了足够的信息来获得包树的完整图片,从而减少了读取包的需要。json文件,并允许显著的性能改进。
结构
上面这张图是 package.lock.json
的属性描述,文章将只挑几个重要的介绍,而详细部分可以参考 package-lock.json - npm Docs
其中 name
和 version
属性是源自 package.json
文件,如果不一致则可能是修改了 package.json
同时再也没有 npm
的相关操作
啥操作能够引起 package-lock.json
的更新?比如 npm uninstall | npm install ...
而 lockfileVersion
是 npm
对于 package.lock.json
的一个版本号,比如
npm V5 and npm V6
是1
- 兼容
npm V7
及以前的npm
版本的package.lock.json
的npm
版本是2
npm V7
以上且不兼容npm V7
以前的npm
版本的package.lock.json
的npm
版本是3
然后就来到了 package.lock.json
最重要的的属性,它是 package.lock.json
作用的体现
安装完全相同的依赖关系
这也是为什么叫 *.lock.*
的原因,就是锁住 node_modules
,让项目中的其它成员在远程拉去代码的时候能够安装相同的 node_moduels
其实现就是依靠 packages
属性,来看一下 packages
的结构
实际的 package.lock.json
的 packages
如下
{
// ...
"packages": {
"node_modules/prettier": {
"version": "2.8.0",
"resolved": "https://registry.npmmirror.com/prettier/-/prettier-2.8.0.tgz",
"integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==",
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
}
},
},
// ...
}
对应的 package.json
{
// ...
"dependencies": {
// ...
"prettier": "^2.8.0"
}
}
你会发现,prettier
的 version
从 ^2.8.0
变到了 2.8.0
,这里就要科普一下对于 Node
来说 ^
这种模块版本前缀的含义了
~x.y.z
: 匹配大于 x.y.z 的 z 的最新版
^x.y.z
: 匹配大于 x.y.z 的 y.z 的最新版
*
: 任意版本,一般是最后一次正式发布版本(包括非 latest tag),不是最大版本号版本
总而言之,以 ^ | ~ | *
作为前缀的版本号都是表示一个范围区间的所有版本号,而不是一个确定的版本号,比如 ^2.8.0
,它可以被安装为 2.9.0
、2.8.1
或者 2.9.1
...,而 2.8.0
就只能是 2.8.0
因此 packages
给 npm
提供了一个固定的版本值,在其它项目成员去 npm install
的时候都会得到同样的 node_modules
,保证了开发时的一致