这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战
在执行npm install的时候,就会在当前目录生成一个package-lock.json的文件,该文件有什么作用呢?
npm 的依赖版本管理非常宽松,同一个项目一天之内可能会 install 到不同版本的依赖,依赖包的升级有可能会给你的项目带来 bug,这时候 shrinkwrap 应运而生了,但是,几乎所有人都懒得写,所以,在受到 yarn.lock 的强烈冲击之后,npm 还是决定在 5.0.0+ 版本默认生成 package-lock.json,就是说你现在不需要写 npm-shrinkwrap.json 了。
package.json里面定义的是版本范围(比如^1.0.0),这里举个例子:
"dependencies":{
"@types/node":"^8.0.33"
}
这里的 ^ 符号是定义了 向后(新)兼容依赖,指如果types/node的版本是超过8.0.33,并在大版本号(8)上相同,就允许下载最新版本的types/node库包,例如实际上可能运行npm i的时候下载的具体版本是8.0.35
所以具体跑npm install的时候安的什么版本,要解析后才能决定
大多数情况下这种向新兼容依赖下载最新库包的时候都没什么问题,可是因为npm 是开源世界,各种库包的版本语义可能并不相同,有的库包开发者并不严格遵守这一原则:相同大版本号的同一个库包其接口符合兼容要求。
这个时候用户就很头疼了:在完全相同的node.js代码库,不同时间或者不同npm下载源下,下载的各个依赖库包版本可能有所不同,有时候甚至都完全不兼容。因此才诞生了package-lock.json功能,为的是让开发者知道,只要你保存了源文件,到一个新的机器或者新的下载源,只要按照这个package-lock.json所标识的具体版本下载依赖库包,就能确保所有库包与你上一次安装的完全一样。
package-lock.json里面定义的依赖关系树,可以称之为逻辑树(logical tree),而node_modules文件夹下才是npm实际安装的确定版本的东西,这里面的文件夹结构我们可以称之为物理树(physical tree)。
安装过程中有一些去重算法,所以你会发现逻辑树结构和物理树结构不完全一样。
package-lock.json可以理解成对结合了逻辑树和物理树的一个快照(snapshot),里面有明确的各依赖版本号,实际安装的结构,也有逻辑树的结构。
其最大的好处就是能获得可重复的构建(repeatable build),当你在CI(持续集成)上重复build的时候,得到的artifact是一样的,因为依赖的版本都被锁住了。在npm5以后,其内容和npm-shrinkwrap.json一模一样。