03-package.json 和 package-lock.json的作用和意义
我们每次,去npm install xxx会把内容记录到package.json文件中,下载的包都会发生变化,为了系统的稳定性考虑,每次执行完npm install之后会对应生成package-lock文件,该文件记录了上一次安装的具体的版本号。
根据官方文档,package-lock.json 是生成的系统当前安装的库的具体来源和版本号,锁定版本。
当你执行npm install的时候, node会先从package.json文件中读取所有dependencies信息,然后根据dependencies中的信息与node_modules中的模块进行对比,没有的直接下载,node是从package.json文件读取模块名称,从package-lock.json文件中获取版本号,然后进行下载或者更新。
当package.json与package-lock.json都不存在,执行"npm install"时,node会重新生成package-lock.json文件,然后把node_modules中的模块信息全部记入package-lock.json文件,但不会生成package.json文件。但是,你可以通过"npm init --yes"来生成package.json文件
**自npm 5.0版本发布以来,npm i的规则发生了三次变化。**
1、npm 5.0.x 版本,不管package.json怎么变,npm i 时都会根据lock文件下载
package-lock.json file not updated after package.json file is changed · Issue #16866 · npm/npm
这个 issue 控诉了这个问题,明明手动改了package.json,为啥不给我升级包!然后就导致了5.1.0的问题...
2、5.1.0版本后 npm install 会无视lock文件 去下载最新的npm
然后有人提了这个issue why is package-lock being ignored? · Issue #17979 · npm/npm
控诉这个问题,最后演变成5.4.2版本后的规则。
3、5.4.2版本后 why is package-lock being ignored? · Issue #17979 · npm/npm
大致意思是,如果改了package.json,且package.json和lock文件不同,那么执行`npm i`时npm会根据package中的版本号以及语义含义去下载最新的包,并更新至lock。
如果两者是同一状态,那么执行`npm i `都会根据lock下载,不会理会package实际包的版本是否有新。
总结:
package-lock.json文件是锁定当前项目依赖的小版本(具体哪个版本),及下载安装这个版本的源信息(如下载源),在node_modules中的对应关系,还有一个安装如果依赖了多个别的插件,也会把这种对应关系描述出来。当然了,我们压根也不会去看这些东西。
package.json是安装的当前大版本的最新版本,因为是^开头,但是package.json中不建议固定写死具体某个版本号,因为它可能还有还有别的依赖,别的版本也都是^,你的这次版本固定可能下次别人更新就不行了,所以锁定版本有我们的lock文件去做。
package.json中的某个,如果更新了(就是lock和package.json有差异了),那么lock里也会随着更新。但是lock里已经记录到了package.json中能正常运行项目的所有小版本依赖了,下次别人再npm i 安装依赖的时候,就会从lock锁定的这些信息中去安装项目依赖。
其实用一句话来概括很简单,就是锁定安装时的包的版本号,并且需要上传到git,以保证其他人在npm install时大家的依赖能保证一致。
引用知乎@周载南的回答
根据官方文档,这个package-lock.json 是在 `npm install`时候生成一份文件,用以记录当前状态下实际安装的各个npm package的具体来源和版本号。
它有什么用呢?因为npm是一个用于管理package之间依赖关系的管理器,它允许开发者在pacakge.json中间标出自己项目对npm各库包的依赖。你可以选择以如下方式来标明自己所需要库包的版本
这里举个例子:
"dependencies": {
"@types/node": "^8.0.33",
},这里面的 向上标号^是定义了向后(新)兼容依赖,指如果 types/node的版本是超过8.0.33,并在大版本号(8)上相同,就允许下载最新版本的 types/node库包,例如实际上可能运行npm install时候下载的具体版本是8.0.35。波浪号
大多数情况这种向新兼容依赖下载最新库包的时候都没有问题,可是因为npm是开源世界,各库包的版本语义可能并不相同,有的库包开发者并不遵守严格这一原则:相同大版本号的同一个库包,其接口符合兼容要求。这时候用户就很头疼了:在完全相同的一个nodejs的代码库,在不同时间或者不同npm下载源之下,下到的各依赖库包版本可能有所不同,因此其依赖库包行为特征也不同有时候甚至完全不兼容。
因此npm最新的版本就开始提供自动生成package-lock.json功能,为的是让开发者知道只要你保存了源文件,到一个新的机器上、或者新的下载源,只要按照这个package-lock.json所标示的具体版本下载依赖库包,就能确保所有库包与你上次安装的完全一样。
原来package.json文件只能锁定大版本,也就是版本号的第一位,并不能锁定后面的小版本,你每次npm install都是拉取的该大版本下的最新的版本,为了稳定性考虑我们几乎是不敢随意升级依赖包的,这将导致多出来很多工作量,测试/适配等,所以package-lock.json文件出来了,当你每次安装一个依赖的时候就锁定在你安装的这个版本。
那如果我们安装时的包有bug,后面需要更新怎么办?
在以前可能就是直接改package.json里面的版本,然后再npm install了,但是5版本后就不支持这样做了,因为版本已经锁定在package-lock.json里了,所以我们只能npm install xxx@x.x.x 这样去更新我们的依赖,然后package-lock.json也能随之更新。
假如我已经安装了jquery 2.1.4这个版本,从git更新了package.json和package-lock.json,我npm install能覆盖掉node_modules里面的依赖吗?
其实我也有这个疑问,所以做了测试,在直接更新package.json和package-loc.json这两个文件后,npm install是可以直接覆盖掉原先的版本的,所以在协作开发时,这两个文件如果有更新,你的开发环境应该npm install一下才对。