npm版本锁定

背景

源起于同事找我帮忙排查一个认为诡异的问题。

同样的代码,同样的package.json本地和流水线部署效果不一样。问我可能是什么原因,我当时想到的可能就两种情况:

  1. 依赖包的版本不一样
  2. 流水线本身存在问题,比如没有拉到最新的代码?

我简单提供用排除法的思路让她走了一遍,排除了不是最新代码的问题,然后让其对比了一下pacage-lock.json文件,的确发现了依赖包的版本变了,当手动在package.json锁死了本地使用的版本号之后,再执行部署则没有问题。

所以最终问题出在package-lock.json上,那为什么package-lock.json每次跑流水线的时候都会变化呢,是因为流水线脚本里部署前端时脚本里会有:

1.npm clean

2.rm- rf node_modules

3.npm i …等步骤

所以导致每次会更新package-lock.json,那我们提交的package-lock.json就失去了它的价值,即可能每次CI都会有不同版本的包依赖。

经过这次的排查,遂记录一下锁包的个人理解。

开始

package-lock.json

npm 关于package-lock.json的解释说的挺清楚了。主要作用锁定(描述)包依赖关系及其子依赖项。保证对其他开发人员或其他环境安装包的依赖关系一致。

如图:eslint-plugin-react依赖树

修改node_modules或package.json将自动生成package-lock.json。 它描述了包版本的依赖树,使得后续可以保证无论在哪儿安装能够生成相同的依赖树(也就是相同的包版本),而不管中间依赖性更新如何。

每当我们运行更改依赖项的NPM命令时,如npm i 或npm uninstall 或npm i 等,都将更新包锁定即更新package-lock.json文件。

所以每次提交时必须把package-lock.json也提交到git。

执行npm i 时会读取根据package.json创建的依赖项列表,并使用package-lock.json来通知哪些版本的这些依赖项需要安装。 如果依赖项不在package-lock.json中,它将通过npm i 添加。

根据上面总结的信息,我理解解决上述问题的其中一个方案就是每次CI的时候只需要拉代码之后再npm i 即可,从而保持依赖一致。

npm ci

在深入了解package-lock.json的过程中,npm ci进入了我的视线,详见npm ci

npm ci(ci:持续集成)直接从package-lock.json安装依赖关系,并使用package.json验证是否存在不匹配的版本。 如果缺少任何依赖项或具有不兼容的版本,则会抛出错误。

因为npm ci是基于package-lock.json进行安装,所以就体现了该命令在包一致性上的作用,在需要重复构建、持续集成等场景下好用。

前提:

必须有package-lock.json文件,即项目第一次初始安装时不能用npm ci,这也说明了为什么上面章节谈到package-lock.json也需要提交到git,这也是原因之一。

所以另一个方案就是每次CI的时候只需要拉代码之后再npm ci 即可,也可保持依赖一致(前提是package.json、package-lock.json每次都进行了同步提交)。

npm i vs npm ci

  1. npm ci不会更新package-lock.json和package.json,即npm ci 不能更新依赖。
  2. npm ci必须基于package-lock.json。
  3. 一般情况下npm ci安装速度会更快。npm ci时如果存在node_modules则会先删除node_modules。
  4. 初始安装以及更新依赖时,只能使用npm i。

另一个问题:咋个解决package-lock.json冲突

这是一个延申出来的问题,因为需要提交package-lock.json,由于一些原因就可能出现冲突的情况,那咋解决呢?

  1. 最好别上来就先删除package-lock.json,人是自动生成的没必要跟它较劲。从基线上拉一个package-lock.json文件下来。
  2. 处理package.json的冲突。
  3. 执行npm i。

参考:

本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。