package-lock.json 生成逻辑
之前我们项目经常会出现执行 npm i 后 package-lock.json 被更改的问题,但是经常是我们觉得不应该出现被更改的情况而被更改了,看了一下 package-locks | npm Docs 官方文档,并结合实践分析了一下可能的原因,下面的内容都是针对 npm@7 以下的情况而言的,npm@7 更新了 lockfiles 的版本,具体会另开文章介绍
package-lock.json 生成逻辑
npm@5 以后 npm 会根据 package.json 生成 lockfiles 文件,目的就是为了保证生产和线上编译或者团队开发时大家生成 node_modules tree 是一致的,但是即使是这样不同版本的 npm 对于 lockfiles 的处理逻辑是不同的,我只验证了最新版本,之前的未经验证
5.0.x 该版本下 npm 忽略 package.json 的变化,只会根据 lockfiles 下载 node_modules
5.1.0 - 5.4.2 npm 又变成了会错误的忽略 lockfiles 去下载 node_modules
5.4.2 这版的逻辑我觉得是最自洽的 https://github.com/npm/npm/issues/17979#issuecomment-332701215
总结起来就是如果我们修改了 package.json 里包的版本,如果新的包的版本和与 lockfiles 里包的版本对照是不符合 semver 规范的,那么,lockfiles 里对应的 version 就会被更新
实例分析
只是简单描述一下 lockfiles 生成的逻辑 我们现在有三个 package,
在这种情况下 package-lock.json, 会生成下面类似的结构
简单说会以当前 package.json 包里对应包符合要求的最新版记录在 lockfiles 里,如果后续无论是直接依赖的 A 发版,或者间接依赖的 B, C 发版,只要我们不动 package.json, lockfiles 都不会重新生成 A 发布了新版本 1.1.0,虽然我们 package.json 写的是 ^1.0.0 但是因为 lockfiles 的处在,npm i 并不会自动升级,我们可以手动运行 npm i A@1.1.0 来实现升级因为 1.1.0 版本与 lockfiles 里记录的 A@1.0.0 是不一致的,因此会更新 lockfiles 里的 A 的版本为 1.1.0 B 发布了新版本 1.0.1, 1.0.2, 1.1.0, 此刻如果我们不做操作是不会自动升级 B 的版本的,但如果此刻 A 发布了 1.1.1,虽然并没有升级 B 的依赖,但是如果我们项目里升级 A@1.1.1,此时 lockfiles 里会把 B 直接升到 1.1.0 ,因为此刻^1.0.0 的最新版本就是 1.1.0 经过这些操作后 package.json, lockfiles 变成
这个时候我们将 B 加入我们项目的依赖, B@^1.0.0
我们执行这个操作后,lockfiles 并没有被改变,因为现在 lockfiles 里 B@1.1.0 满足 ^1.0.0 的要求 但是如果我们将 B 的版本固定到 2.x 版本, lockfiles 就会发生改变
因为 B 的版本出现了冲突,npm 使用嵌套描述了这种行为 我们实际开发中并不需要关注这种生成的算法逻辑,我们只需要了解,lockfiles 的生成逻辑是为了能够精准的反映出我们 node_modules 的结构,并保证能够这种结构被还原
package-lock.json 可能被意外更改的原因
新增或者删除了一些包,但是没有及时 install 我们可以想象出现这样一种场景,a 同学给 package.json 添加了一个 package,但是没有执行 npm install,代码被 push 上去后,b 同学执行 npm i,就会发现 lockfiles 被更改了
挪动了包的位置 将部分包的位置从 dependencies 移动到 devDependencies 这种操作,虽然包未变,但是也会影响 lockfiles,会将部分包的 dev 字段设置为 true
registry 的影响 经过实际使用发现,如果我们 node_modules 文件夹下的包中下载时的的 registy 与 lockfiles 中包即使 version 相同,但是 registy 是不同,执行 npm i 时 可能还存在其他的原因,但是 lockfiles 是不会无缘无故被更改的,一定是因为 package.json 或者 node_modules 被更改了,因为 正如上面提到的 lockfiles 为了能够精准的反映出我们 node_modules 的结构
开发的建议
目前来看,npm install 是足够可靠的,他能保证根据 lockfiles 还原出开发时的 node_modules,但是为了防止出现刚刚提到的意外情况,除非涉及到对包的调整,其他情况下建议使用 npm ci 来安装依赖,会避免异常的修改 lockfiles,持续集成工具中更推荐是用 npm ci,保证构建环境的准确性,npm i 和 npm ci 的区别可以参考官方文档
最后更新于