一、始终不正确的依赖版本号
在晨会上,组员们逐一分享了昨日的工作进展。期间,一位组员分享了他遇到的一个困难:“昨天,当我尝试安装A部门提供的一个组件库时,发现其中一个依赖的版本号始终不正确,导致组件库报错无法使用,我向A部门咨询,但他们一直坚持说组件库的依赖版本号设置是没有问题的。那个依赖他们所要求的版本是3.5.1-alpha.5
,而我安装后版本都是3.5.1
。”
“等会儿我帮你看看。很可能是依赖版本号前面的符号引起的问题。”
二、检查组件库的package.json
文件
项目使用pnpm
作为包管理工具,因此需要在node_modules
文件夹下的.pnpm
目录中查找该组件库包的代码。
在找到的package.json
文件中,我注意到dependencies
字段里的依赖版本号前都加了^
符号。
到这里,我心里就有谱了,应该是^
符号搞得鬼。
三、^
符号的作用
在这之前先介绍一下依赖版本号的组成,在语义版本控制中,依赖版本号通常由主版本号、次版本号、修订号三个主要部分组成,这三部分通过点号(.
)分隔,例如:3.5.1
。还可以通过在版本号后添加连字符(-
)和一个标识符(alpha
、beta
或 RC
)来指定预发布版本,如 3.5.1-alpha.5
。还可以通过在版本号后添加加号(+
)和一些元数据来指定,如 3.5.1+build.456
^
符号在 package.json
文件中用于指定依赖包版本范围,允许自动更新到当前主版本号中的最新稳定版本,但不会更新到下一个主版本号以避免破坏性更改。
四、搞笑的版本发布
那个无论怎么安装但是版本号都不对的依赖,在组件库中的版本被指定为 ^3.5.1-alpha.5
。这意味着当我们使用 pnpm
包管理器安装此依赖时,它会选择安装主版本号为 3
的最新稳定版本,即 3.5.1
,尽管 3.5.1-alpha.5
的发布时间晚于 3.5.1
。
这里的关键在于,3.5.1-alpha.5
被视为预发布版本,包管理器将其认定为不稳定的。即便它是按时间顺序的最新版本,包管理器仍会优先选择安装稳定版本 3.5.1
,以避免潜在的破坏性更改。
因此,即使后续再发布的或之前已经发布的其他预发布版本,使用 ^
符号的安装命令依然会默认安装 3.5.1
版本。
这意味着,尽管 A 部门出于修复 3.5.1
版本中的错误而发布了 3.5.1-alpha.5
,并且在组件库中使用 ^
符号指定版本号,但这实际上并未达到预期目的,因为安装时仍会回退到 3.5.1
的稳定版本。
更严重的是,如果生产环境的组件库中指定的依赖版本为 ^3.5.1-alpha.4
,那么尽管 3.5.1-alpha.4
版本本身不会引起组件库报错,但如果重新部署生产环境,这个依赖将会被更新到 3.5.1
版本,这是一个已知会导致组件库报错的版本,从而可能触发一次生产事故。
五、如何自救
如果跟 A 部门说明情况后,A 部门仍然坚持说组件库的依赖版本号设置是没有问题的,我们该如何自救呢?
可以使用 resolutions
,此字段允许您指示 pnpm
覆盖依赖关系图中的任何依赖项,可以利用来锁定依赖版本,来完成自救。
在package.json
文件中添加如下配置:
"resolutions": {
"xxx": "3.5.1-alpha.5"
}