一次 yarn 安装依赖失败,让我重新认识了 NPM 版本号规则

开发 前端
考虑一个问题,项目第一次添加一个模块的依赖是 ^1.2.3​,过了两周另一个同事需要修这个项目,此时依赖已经更新到 1.3.0 他在重新安装后就会得到最新的版本,这会带来一个问题,每个人得到依赖版本不一致,该如何确保团队成员的依赖版本都是一致呢?

现代的前端开发、Node.js 后端开发中 NPM 包管理是最基础也是最关键的一部分,本文将从一个问题开始,阐述 NPM 版本控制的工作原理,我相信这是每一个使用了 NPM 的开发人员都应该熟悉的知识。

一个依赖安装失败示例

事情的经过是前一天测试还一切正常,第二天部署时却提示 yarn 安装依赖失败,下面是本地复现的结果,如下图所示:

图片

yarn 安装失败

一个明显的提示是 bson@5.0.0​ 这个依赖不再支持 Node.js 14.20.1​ 以下版本,但是项目的 dependencies​ 中也没有指定这个包啊,了解 MongoDB 的同学应该知道 bson​ 是 Mongo​ 实现的一个类 JSON 的二进制存储格式。

为了一探究竟,执行 yarn --ignore-engines​ 先忽略这个引擎检测,看下 yarn.lock 文件中 bson 的依赖关系。

mongoose@^5.3.0​ 是项目中的依赖,实际安装后使用的版本为 5.13.5​,之后又依赖了 @types/mongodb​,问题来了,这里竟然使用了 @types/bson: *​ 要知道在 NPM 的版本号规则里 *​ 号是不会锁定版本的,每次都会升级为最新版本,也就是最后的 bson: 5.0.0。

图片

查了下 bson​ 这个库的 CHANGELOG 发现其在 2023-01-31​ 号发布了 5.0.0,要求 Node.js 版本必须大于 14.20.1,上面报错显然当前版本不满足。

库的版本升级很正常,了解 NPM 版本号规则的同学应该知道 “bson: 5.0.0 ”  这是一个大版本,会存在不向前兼容的情况,这里的问题在于 ​@types/mongodb​ 直接使用了 ​@types/bson: *​,每次安装都会升级到最新,是有点不讲 “码德”,这里是个坑,NPM 上查了 @types/mongodb 这个包,发现已经被废弃了,如下图所示:

图片

mongoose​ 这个包的影响版本为:​mongoose 5.11 ~ 5.13.15。

这里先抛出一个问题:“为什么安装时使用的 mongoose@^5.3.0​ 安装成功后却变成了 5.13.15”?

NPM 的语义版本控制

在发布 NPM 模块新版本时,建议遵循 “语义版本控制” 考虑使用这样的版本号x.y.z 控制,如下所示:

图片

版本号规则:

  • 主版本:做了不兼容的 API 修改,不会向前兼容,一般也称为大版本,当项目依赖需要升级到大版本时需要注意。
  • 次版本:通常是做了向前兼容的新功能增加,一般也称为小版本。
  • 补丁版本:修复现有的一些错误,也是向前兼容的。

在发布 NPM 包时建议从 1.0.0 开始,例如:

  • 1.0.0:新产品首次发布。
  • 1.0.1:向前兼容的补丁版本,修改第 3 位数。
  • 1.1.0:向前兼容增加新特性,增加中间数字,将最后一位置为 0。
  • 2.0.0:不向前兼容的更新,增加第一位数字,将第二、三位数置为 0。

语义化版本号的几种表示方法:

  • ^1.1.2:^ 是 NPM 安装后的默认符号,保持高版本不升级,次版本、补丁版本升级到最新,例如:^1.1.2 等价于 1.1.2 >= ^1.1.2 < 2.0.0。
  • ~1.1.3​:波浪符 ~ 只会升级补丁版本,例如:~1.1.3 等价于 1.1.3 >= ~1.1.3 <1.2.0。
  • 1.1.3:不加任何符号表示锁定了这个版本,不会进行任何升级。
  • * 或 "":* 号或者空字符 "",不会锁定版本,每次都会升级到最新版本,前面提的问题就是这个导致的。
  • 1.0.0-alpha.1:使用 alpha、rc 等标识的表示该版本是一个预发布版本,该版本可能无法满足预期的兼容性需求,正式环境不要用。
  • 一个非语义话版本号的示例 v1.0.0:在一些版本控制的系统中通常用 v 表示版本号,例如 git tag v1.0.0,但它并不是语义化版本号。

了解了语义化版本号规则后,应该要知道上面提出的一个问题:“为什么安装时使用的 mongoose@^5.3.0​ 安装成功后却变成了 5.13.15​”,因为版本号前加 ^ 符号,它表示的是第一位保持不变、最后两位升级到最新。

依赖锁定 - 解决版本不一致问题

考虑一个问题,项目第一次添加一个模块的依赖是 ^1.2.3​,过了两周另一个同事需要修这个项目,此时依赖已经更新到 1.3.0 他在重新安装后就会得到最新的版本,这会带来一个问题,每个人得到依赖版本不一致,该如何确保团队成员的依赖版本都是一致呢?

解决依赖版本不一致的问题一种方法是 “固定依赖版本”,但在实际做法中这种很少见,大多数时候没有意识到一个问题 “安全修复”,通过版本号前加 ^ 或 ~ 符号我们可以得到补丁版本错误修复、向前兼容的小版本新功能。

解决依赖版本不一致的另一种方法是通过 lock 文件(NPM 中的 package-lock.json​ 或 yarn 中的 yarn.lock )来解决同一个项目团队成员之间依赖版本不一致的问题,在使用 npm 或 yarn 安装之前会先检查 lock 文件上的版本,并来安装它们,有必要将 lock 文件推送至 git 仓库。

如果需要将依赖项更新到指定范围的最新版本,只需要执行 npm update 命令,该命令会遵循语义化版本控制对依赖进行升级,同时也会更新 lock 文件。

责任编辑:武晓燕 来源: 编程界
相关推荐

2019-09-02 08:53:46

程序员

2023-08-02 08:46:02

Go版本号规则

2014-01-06 11:23:54

Mesos设计架构

2021-04-22 21:15:38

Generator函数生成器

2019-10-31 13:40:52

JavaPHP编程语言

2019-02-24 21:27:26

物联网网关物联网IOT

2016-11-07 11:34:28

数据可视化大数据

2016-12-13 15:41:40

JavaHashMap

2022-09-08 13:58:39

Spring高并发异步

2020-09-17 07:08:04

TypescriptVue3前端

2009-11-26 15:07:28

Cisco路由器接口

2021-11-11 05:00:02

JavaMmap内存

2020-10-15 07:13:53

算法监控数据

2023-05-03 09:09:28

Golang数组

2017-01-03 17:22:16

公共云安全

2022-07-11 13:58:14

数据库业务流程系统

2023-01-16 14:49:00

MongoDB数据库

2018-06-05 15:02:32

2015-03-19 10:15:54

程序员价值程序员价值

2010-10-22 11:10:24

软考
点赞
收藏

51CTO技术栈公众号