npm依赖管理

1,060 阅读4分钟

依赖管理的目标

1、管理依赖

项目依赖资源一版不会提交到git,只需要声明依赖,使用的时候去下载即可。git上只保存对依赖的“声明”。

2、管理更新

依赖的资源有更新,如何自动跟新到项目中(尤其是bug类的修复版本)。

npm版本号采用语义化的版本声明方式(semver):

版本格式:主版本号.次版本号.修订号,版本号递增规则如下:

  1. 主版本号:当你做了不兼容的 API 修改,
  2. 次版本号:当你做了向下兼容的功能性新增,
  3. 修订号:当你做了向下兼容的问题修正。
  4. 有时候为了表达更加确切的版本,还会在版本号后面添加标签或者扩展,来说明是预发布版本或者测试版本等

理论上,如果所有的npm包都能采用semver方式管理版本,在项目中对依赖的声明只需要将依赖的npm包主版本号固定即可(npm默认的处理方式就是如此)。但是理想很丰满,现实很骨干,并不是所有npm包都能遵守这个规范,因此可能导致在某个时间再次安装依赖时,存在部分项目所依赖的npm包不向下兼容,导致的项目报错。因此固定依赖的npm包的版本(包括直接依赖和间接依赖)成为一种需求。

package.json对依赖的声明

package.json中的dependencies和devDependencies字段声明了项目的直接依赖资源,声明格式如下:

"chalk": "^2.3.2"

key值表示npm包名,value指定版本信息,版本信息支持三种语法:

测试版本号计算可以到semver计算器测试

语法 示例 说明 设置方式
^ ^1.1.1 表示安装版本1.1.1到2.0.0(不包括2.0.0)之间的最新版本,即只控制主版本 (默认)npm config set save-prefix='^'
~ ~2.2.2 表示安装2.2.2到2.3.0(不包括2.3.0)之间的最新版本,即控制主版本和次版本 npm config set save-prefix='~'
xxx.xxx.xxx 3.3.3 固定版本号
>,<,<=,>=,- >4.4.4 指定安装版本范围,如4.4.1 - 4.5.1(注意“-”两侧的空格)表示4.4.1<= 版本号 <=4.5.1,等价于>=4.4.1<=4.5.1
|| ^2 <2.2 || > 2.3 多个条件组合

由上表可知,默认情况下在不同的时期执行npm install安装的包可能只有主版本号相同,有潜在运行不一致的风险。就算在package.json中使用固定版本的方式声明版本号,也只能解决直接依赖npm包版本问题,间接依赖的npm包还是有可能存在不一致情况。

使用npm shrinkwrap

执行以下命令,会在当前目录下生成npm-shrinkwrap.json文件,该文件记录了项目的详细依赖信息(如实反映,版本号固定)。

npm shrinkwrap

当项目中存在npm-shrinkwrap.json文件时,执行npm install会根据该文件信息去安装依赖包,因此每次安装的依赖都会完全相同,因此可以使用该命令来确保项目依赖的一致性。

注意该命令执行后,若后面有新增或修改或删除依赖,依赖信息不会自动更新到该文件,要再次执行npm shrinkwrap命令。

借助NPM5+的package-lock.json文件

在npm 5版本后,每次执行npm install xxxx会额外在执行一个动作,将项目的依赖信息跟新到package-lock.json文件。这是一个自动过程,每次新增或修改或删除依赖都会将项目依赖同步反应到改文件。

当项目中存在package-lock.json文件时,执行npm install会根据该文件信息去安装依赖包,因此每次安装的依赖都会完全相同,因此可以使用该命令来确保项目依赖的一致性。

当项目中存在package-lock.json文件时执行npm shrinkwrap会根据package-lock.json文件创建npm-shrinkwrap.json文件同时删除package-lock.json文件。执行npm install命令时,npm-shrinkwrap.json文件优先级会高于package-lock.json。

使用npm ci安装

条件:项目中必须有一个package-lock.json或npm-shrinkwrap.js

npm ci与npm i主要有以下的区别。

  • npm i依赖package.json,而npm ci依赖package-lock.json。
  • 当package-lock.json中的依赖于package.json不一致时,npm ci退出但不会修改package-lock.json。
  • npm ci只可以一次性的安装整个项目依赖,但无法添加单个依赖项。
  • npm ci安装包之前,会删除掉node_modules文件夹,因此他不需要去校验已下载文件版本与控制版本的关系,也不用校验是否存在最新版本的库,所以下载的速度更快。
  • npm ci安装时,不会修改package.json与package-lock.json。