前言
有小伙伴提出:“为什么执行 npm install 时有些包不会安装,每次都得删掉 node_modules 和 package-lock 然后重新安装……”,看到这个问题,我陷入了沉思,闲暇查阅了资料,好好地理了一下思绪。在解答疑惑的同时,先记录几个术语介绍。
版本控制规则
a.b.c
- a 表示主版本号,b表示次版本号,c 表示补丁更新
- 当只是简单的修复了 bug, 没有添加任何新功能,或者修改旧功能时, 就更新补丁号 c;
- 当添加了新的功能, 但没有破坏原有的功能,就更新次版本号 b;
- 当做了重大修改,导致新版本不兼容旧代码时,就更新主版本号 a
package.json 版本控制举例
- 指定版本:比如 “antd”: “3.10.7”或”antd”: “=3.10.7”,表示安装3.10.7的版本
:比如 “antd”: “3.10.7”,表示安装3.10.x的最新版本(不低于3.10.7),但是不安装3.11.x,也就是说安装时不改变大版本号和次要版本号- ^:比如 “antd”: “^3.10.7”,表示安装3.10.7及以上的版本,但是不安装4.0.0,也就是说安装时不改变大版本号
package.json
1 | { |
生成方式:执行 npm init 命令
主要作用:描述项目及项目所依赖的模块信息
package-lock.json
生成方式:从
npm 5
版本之后只要使用npm install
命令下载,就会自动生成package-lock.json
文件。保证我们的应用程序依赖之间的关系是一致的,兼容的;适合多人协作开发时保证每个人的依赖版本是一致的主要作用:
- 描述
node_modules
文件中所有模块的版本信息,模块来源及依赖的小版本信息 - 当版本升级,使用
npm install
命令时,会安装package.json
中指定的大版本的最新版本。如package.json
中指定版本"dependencies": { "webpack": "^2.0.0" }
,则package-lock.json
会按照{"webpack": "2.7.0"}
版本升级。在保证大版本号前提下的最新版本。webpack "2.7.0"
是"2.x.x"
的最高版本 - 加快了
npm install
的速度,因为package-lock.json
文件中已经记录了整个node_modules
文件夹的树状结构,同时记录了模块的下载地址
- 描述
使用yarn同样也会自动生成
package-lock.json
文件,但是cnpm不会自动生成,并且也不会读取package-lock.json
文件,只根据package.json
下载依赖
更新依赖
在npm 5.x之前,我们可以直接更改package.json
中的版本号,再npm install
就可以直接更新了,但是5.x之后由于是根据package-lock.json
安装依赖,所以我们只能使用npm install xxx@x.x.x
去更新依赖,这样package-lock.json
也会同步更新。
package.json 与 package-lock.json
package.json
里面定义的是版本范围(比如^1.0.0
),具体跑npm install
的时候安的什么版本,要解析后才能决定,这里面定义的依赖关系树,可以称之为逻辑树(logical tree)。node_modules
文件夹下才是npm实际安装的确定版本的东西,这里面的文件夹结构我们可以称之为物理树(physical tree)。安装过程中有一些去重算法,所以你会发现逻辑树结构和物理树结构不完全一样。package-lock.json
可以理解成对结合了逻辑树和物理树的一个快照(snapshot),里面有明确的各依赖版本号,实际安装的结构,也有逻辑树的结构。
为什么 package-lock.json 会出现呢?
大多数情况这种向新兼容依赖下载最新库包的时候都没有问题,可是因为npm是开源世界,各库包的版本语义可能并不相同,有的库包开发者并不遵守严格这一原则:相同大版本号的同一个库包,其接口符合兼容要求。这时候用户就很头疼了:在完全相同的一个nodejs的代码库,在不同时间或者不同npm下载源之下,下到的各依赖库包版本可能有所不同,因此其依赖库包行为特征也不同有时候甚至完全不兼容。
因此npm最新的版本就开始提供自动生成package-lock.json功能,为的是让开发者知道只要你保存了源文件,到一个新的机器上、或者新的下载源,只要按照这个package-lock.json所标示的具体版本下载依赖库包,就能确保所有库包与你上次安装的完全一样。
简单的说,就是为了保证协作开发的时候,大家下载的包都是一样的,都是同个版本,同个地址下载。
这就不得不回到文章开头的问题,为什么会要删除 node_modules 和 package-lock 然后重新安装呢?
大佬回答:可能是不同系统导致的, MacOs / linux / windows。不同系统下的包依赖(node-sass)不太一样。执行 npm install 时,package-lock.json 检测 package.json 没变,因此使用 package-lock.json 中的包版本进行安装,不同系统下就出问题了。
似乎,这也是 package-lock.json 的一个争议点呢,网上的信息不是很清晰,自己尚未遇到,后续继续关注这个问题~