开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情
目前的前端现代工程化中,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,保证了开发时的一致