深入分析package.json和package-lock.json版本控制关系
前言
本次只谈论二者在控制安装的依赖版本之间的关系,不介绍里面的各项配置。下面会通过举例安装一个依赖rxjs
进行讲解。内容有点多,不想看过程可以直接跳到总结,本篇文章纯属个人分析总结,仅供参考。
1、新建一个项目,执行命令npm init
,会生成package.json文件。如下图:
2、执行命令
npm i rxjs@6.2.0
(选择安装6.2.0版本是为了方便后面的测试)安装好依赖后,rxjs的6.2.0版本安装到dependencies生产依赖下,如下图:
由于npm版本是5+,因此会自动生成package-lock.json文件,package-lock.json文件里会记录并锁定当前package.json里的rxjs版本,如下图:
同时生成node_modules文件,在node_modules下可查看实际安装的rxjs版本,如下图:
在理解版本控制之前,需要理解package.json里安装的依赖版本号代表的意义以及版本号前面符号
~
、^
等代表的意思。
以安装的rxjs版本号6.2.0为例:
6.2.0分别对应major,minor,patch:6是marjor version(主要版本);2是minor version(次要要版本);0是patch version(补丁版本)。
^
:版本号中最左边的非0数字的右侧都用最新的版本数。即更新到最新的次要版本或补丁版本,也就是第2位或第3位会更新到最新版本,其余不变;~
:表示只更新最新的补丁版本;也就是第3位会更新到最新版本,其余不变;
如果版本号前面没有符号,就会安装固定的版本。下面会通过几种情况来分析两个问题:
1、为何package-lock.json可以锁定rxjs版本?
2、当package.json和package-lock.json里的rxjs版本号不一样时,实际安装的rxjs是什么版本?
问题1、package-lock.json为何可以锁定rxjs版本?
package-lock.json的作用:锁定安装时的包的版本号及包的依赖的版本号,以保证其他所有人人在使用
npm install
时下载的依赖包都是一致的。
步骤1、先安装rxjs的一个指定版本6.2.0,参考前言。
步骤2、运行命令rimraf .\node_modules\
(没有rimraf可以执行npm i rimraf -g 全局安装)删除node_modules,执行命令npm i
重新安装依赖,查看node_modules下的rxjs版本。
发现node_modules下的rxjs版本号和package.json里的一致,都是指定的6.2.0版本,rxjs没有更新到最新版本。
步骤3、删除node_modules和package-lock.json文件,只保留package.json文件,如下图:
执行命令
npm i
重新安装依赖,查看package.json、node_modules和package-lock.json里的rxjs版本
发现rxjs版本变成了当前主要版本下的最新版本6.6.7,和package.json里的版本不一致。
总结
通过上面的测试发现:
1、有package-lock.json,安装的实际版本是指定的版本;
2、没有package-lock.json,且rxjs版本号前面加了
^
,安装依赖的时候安装了最新的次版本和补丁版本。说明package-lock.json可以锁定安装的版本。
问题2、当package.json和package-lock.json里的rxjs版本号不一样时,实际安装的rxjs是什么版本?
对于问题2的分析可以从两方面入手
测试一:手动改变package.json里的版本号,重新执行命令npm i
,然后查看node_modules下实际安装的版本;
测试二:手动改变package-lock.json里的版本号,重新执行命令npm i
,然后查看node_modules下实际安装的版本;
测试一:手动改变package.json里的rxjs版本号
第一种情况:主要版本不一致
步骤2、删除node_modules,修改package.json里rxjs的版本,使其主要版本高于
package-lock.json里rxjs的版本,比如改成^7.1.0,如下图:
然后执行命令
npm i
,查看node_modules和package-lock.json里的rxjs版本,如下图:
发现node_modules和package-lock.json里的变成了当前主要版本下的最新版本7.5.7。
步骤3、删除node_modules,修改package.json里rxjs的版本,使其主要版本低于
package-lock.json里rxjs的版本,比如改成^5.5.2,如下图:
然后执行命令
npm i
,查看node_modules和package-lock.json里的rxjs版本,如下图:
发现node_modules和package-lock.json里的变成了当前主要版本下的最新版本5.5.12。
分析第一种情况可知:以当前package.json里的版本^6.2.0为例,手动修改packag.json里的rxjs版本号,如果修改后的主要版本和package-lock.json里的主要版本不一致
,重装rxjs依赖时,会将rxjs升级为当前主要版本下的最新
版本。
第二种情况:主要版本一致,次要版本不一致
步骤1、和第一种情况步骤一一致。
分析第二种情况可知:以当前package.json里的版本^6.2.0为例,手动修改package.json里的rxjs版本号,如果修改后的主要版本和当前版本(package-lock.json)的一致,次要版本不一致
,重装rxjs依赖,如果次要版本大于
当前版本:实际安装的版本为当前主要版本下的最新
版本。如果次要版本小于
当前版本:实际安装的版本为当前
版本。
测试一总结:手动改变package.json里的版本号对实际安装版本的影响
情况一、package.json里版本号前面的符号为^
1、主要版本不一致:实际安装的版本为改后的最新次要版本和补丁版本。
2、主要版本一致,次要版本不一致,比较次要版本:
- 改后 > 当前,实际安装的版本为改后的最新的次要版本和补丁版本。
- 改后 < 当前,实际安装的版本为当前版本。
情况二、package.json里版本号前面的符号为~
1、主要版本或次要版本不一致:实际安装的版本为改后的最新补丁版本。
2、主要版本和次要版本一致,补丁版本不一致,比较补丁版本:
- 改后 > 当前,实际安装的版本为改后的最新补丁版本。
- 改后 < 当前,实际安装的版本为当前版本。
测试二:手动改变package-lock.json里的rxjs版本号
第一种情况:主要版本不一致
步骤2、删除node_modules,修改package-lock.json里rxjs的版本,使其主要版本高于
package.json里rxjs的版本比如改成7.0.1,如下图:
然后执行命令
npm i
,查看package.json、node_modules和package-lock.json里的rxjs版本,如下图:
发现node_modules和package-lock.json里的变成了当前主要版本的最新版本6.6.7,而package.json里的还是^6.2.0。
分析第一种情况可知:以当前package.json里的版本^6.2.0为例,手动修改package-lock.json里的rxjs版本号,如果修改后的主要版本和package.json里的主要版本不一致
,重装rxjs依赖时,会将rxjs升级为当前主要版本下的最新
版本。
第二种情况:主要版本一致,次要版本不一致
步骤1、和情况一步骤一一致。
分析第二种情况可知:以当前package.json里的版本^6.2.0为例,手动修改package-lock.json里的rxjs版本号,如果修改后的主要版本和当前版本(package.json)一致,次要版本不一致
,重装rxjs依赖,如果次要版本大于
当前版本:实际安装的版本为当前
版本。如果次要版本小于
当前版本:实际安装的版本为当前版本前面符号控制的最新
版本。
测试二总结:手动改变package-lock.json里的版本号对实际安装版本的影响
情况一、package.json里版本号前面的符号为^
1、主要版本不一致:实际安装的版本为当前最新的次要版本和补丁版本。
2、主要版本一致,次要版本不一致,比较次要版本:
- 改后 > 当前,实际安装的版本为当前版本。
- 改后 < 当前,实际安装的版本为当前最新的次要版本和补丁版本。
情况二、package.json里版本号前面的符号为~
1、主要版本或次要版本不一致:实际安装的版本为当前最新的补丁版本。
2、主要版本和次要版本一致,补丁版本不一致,比较补丁版本:
- 改后 > 当前,实际安装的版本为当前版本。
- 改后 < 当前,实际安装的版本为当前最新的补丁版本。
总结:
1、为什么package-lock.json可以锁定安装依赖的版本?
- 实际安装依赖的版本(node_modules下)始终和package-lock.json里的版本保持一致。
- package-lock.json锁定项目依赖的依赖。
2、当package.json和package-lock.json里的版本号不一致时,实际安装的依赖是什么版本?
这主要取决于package.json里的版本号前面的符号,以版本号前面有符号和无符号两种情况进行说明。
- 如果版号本前面无符号,则实际安装的版本就是package.json里的固定版本。
- 如果版本号前面有符号:
- 大版本(对于
^
来说,大版本就是版本号第1位;对于~
来说,大版本就是第1位和第2位)不一致,实际安装的版本为版本号前面符号控制的最新版本。 - 大版本一致,比较小版本或补丁版本大小:
- package.json > package-lock.json,实际安装的版本为版本号前面符号控制的最新版本。
- package.json < package-lock.json,实际安装的版本为当前版本。
参考文章:
转载自:https://juejin.cn/post/7154286768466952222