npm i 和npm ci 到底有什么区别?

740 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

npm 是 Node 自带的软件包管理工具,以往我们在多人协同开发过程中经常使用 npm i 来安装/更新项目依赖,但在 NPM v6 版本后,为什么大家更推荐使用  npm ci 了呢! 

npm i 和 npm ci 到底有什么区别?

首先,我们来了解一下执行 npm i 和 npm ci 命令到底发生了什么?

执行 npm i 命令主要做了两件事:

  • 首先,它会根据 package.json 文件,创建node_modules 文件夹并安装对应的依赖版本;

  • 然后, 生成/更新 package-lock.json 文件;

执行 npm ci 命令也做了两件事:

  • 首先,它会删除 node_modules 文件夹;

  • 然后,依照 package-lock.json(或 npm-shrinkwrap.json)文件 创建新得node_modules 文件夹并精准安装对应的依赖版本

ps: npm-shrinkwrap.json文件,是在 NPM v5 版本之前,通过运行npm shrinkwrap命令产生用来精准控制安装依赖版本的文件;

知道了 npm i 和 npm ci 命令都做了什么,我们就知道了为什么推荐使用  npm ci 了,因为它能够精准安装对应的依赖版本

为什么 npm i 不能精准安装依赖?

npm i 不能精准安装依赖主要是因为package.json文件里面的依赖版本往往是一个范围,并不是一个固定的版本,它允许依赖的升级;而package-lock.json 文件,是对package.json文件,做了依赖的版本检查以及梳理后生成的,所以npm ci能够快速精确的安装依赖;

那么什么精准安装依赖?精准安装依赖解决了什么问题?

所谓精准安装依赖,就是不受语义版本控制的影响,精确安装指定的版本依赖,保证了项目的‘完美复制’;

例如:在项目部署的时候,使用 npm ci 保证了依赖版本一致,不会因为出现线上和开发版本不一致而引发的bug;

语义版本控制 semver

语义版本控制简单来说对软件的版本号赋予了语义,软件的版本号通常由版本符号和三个数字组成;

例如版本号:2.1.3其中

  • 第一个数字2代表主版本号,表示进行了不兼容的更新;

  • 第二个数字1代表次版本号,表示以向后兼容的方式添加功能的更新;

  • 第三个数字3代表补丁版本号,表示进行向后兼容的缺陷修复的更新;

  • 2.1.3 指定特定的版本号2.1.3

  • ~2.1.3 当运行 npm update 时,会匹配所有 2.1.x 版本,但是不包括 2.2.0;

  • ^2.1.3 当运行 npm update 时,会匹配所有 2.x.x 版本,但是不包括 3.0.0;

  • *2.1.3 当运行 npm update 时,会匹配安装最新版本;

package-lock.jsonnpm-shrinkwrap.json什么区别?

npm-shrinkwrap.json是在 NPM v5 版本之前,用来精准控制安装依赖版本的,package-lock.json在 NPM v6 版本,用来精准控制安装依赖版本的。package-lock.jsonnpm-shrinkwrap.json更加成熟、简单。

npm-shrinkwrap.json是手动运行npm shrinkwrap命令创建/更新的,而package-lock.json会在修改pacakge.json或者node_modules时自动产生/更新。

并且 npm-shrinkwrap.json会在发布包中出现,而package-lock.jsonnpm 会自动忽略。

一般情况下使用 npm i 是可以的,但是为了防止意外情况发生,建议使用 npm ci 来安装依赖,它可以保护项目环境的准确性,并且因为不用梳理各依赖之间的关系,它比npm i的速度更快。