跳到主要内容

语义化版本(semver)怎么读:谁更新、预发布与依赖范围全讲清

语义化版本号由主版本、次版本、补丁三段组成。本文讲清怎么判断两个版本谁更新,预发布标签的优先级,以及脱字号波浪号范围怎么圈定可升级区间。

发布于 作者 李雷
#语义化版本 #semver #版本号 #依赖管理 #前端工程

语义化版本(semver)怎么读:谁更新、预发布与依赖范围全讲清

每个写过 package.json 的人都见过 ^18.2.0 这种写法,也都被 1.2.91.2.10 谁大这种问题绊过一次。语义化版本(Semantic Versioning,简称 semver)给版本号定了一套确定的规则,读懂它,升级依赖时就不用再靠猜。

三段数字各管什么

一个标准的 semver 长这样:主版本.次版本.补丁,比如 2.4.1。三段各有分工,记住这条就够用大半:

  • 主版本(major)递增,代表有破坏性改动,旧代码可能跑不起来。比如 1.x.x 升到 2.0.0,你要去读迁移指南。
  • 次版本(minor)递增,代表加了新功能,但向后兼容,老用法照样能用。1.4.0 升到 1.5.0 属于这类。
  • 补丁(patch)递增,代表只修了 bug,不加功能也不破坏接口。1.5.01.5.1 就是修了点小毛病。

所以看到 1.9.0 跳到 2.0.0,第一反应应该是警惕;看到 1.9.01.10.0,放心接,只是多了功能。

比较两个版本,关键在按数值读

这是 semver 最反直觉、也最容易踩的一点。很多人下意识用字符串排序,而字符串是逐字符比的。

举个真实例子:1.2.01.10.0 谁更新?字符串排序逐字符读补丁那段,看到 21 之后,会判 1.2.0 更大。但按 semver,次版本要当整数比,2 < 10,所以 1.10.0 才是更新的版本。同理 1.2.10 大于 1.2.9,因为补丁段 10 > 9,而不是按字符 9 排在 1 后面那种读法。

我自己第一次被这条坑,是在一个发布脚本里用了简单的字符串比较,结果灰度版本死活推不上去,排查半天才发现是 1.0.10 被判成比 1.0.9 旧。从那以后,凡是要比版本,我都先丢进 语义化版本比较器 核一遍,它会高亮第一个不同的段,一眼看出问题出在哪。

预发布标签:带横杠的版本更靠前

正式版发布前常有 1.0.0-alpha1.0.0-beta1.0.0-rc.1 这类预发布版本。规范规定,带预发布标签的版本优先级低于对应的正式版。也就是说:

1.0.0-alpha < 1.0.0-rc.1 < 1.0.0

预发布内部按点分标识从左到右比:1.0.0-alpha.11.0.0-alpha.2 旧;纯数字标识排在字母标识之下。还有个容易被忽略的细节,+build.42 这种构建元数据在比较时完全被忽略,1.0.0+build.11.0.0+build.999 是相等的,它只记录产物怎么来的,不影响谁新谁旧。

脱字号与波浪号:依赖范围怎么圈

依赖文件里很少写死一个版本,更多是写一个允许的范围:

  • 脱字号 ^1.2.3:允许最左边那个非零数字不变的所有更新版本。1.9.0 满足,2.0.0 不满足。当主版本是 0 时改锁次版本,^0.2.3 允许 0.2.9 但不允许 0.3.0
  • 波浪号 ~1.2.3:更紧,只允许补丁递增。1.2.9 通过,1.3.0 就被挡在外面。

实务里 ^ 是 npm 默认,适合相信上游遵守 semver 的库;~ 适合你只想拿 bug 修复、不想要新功能的场景。判断某个具体版本到底落不落在范围里,可以直接在比较器的范围框输入运算符核对,省得自己脑补边界。

一组版本一次排序

手里有一堆乱序标签时,挨个比太慢。把 1.0.0、1.0.0-alpha、2.0.0、1.0.0-rc.1、1.2.0 这样一组粘进去,按优先级规则排出来就是 1.0.0-alpha、1.0.0-rc.1、1.0.0、1.2.0、2.0.0,预发布的次序和正式版的位置都摆对。整理更新日志、对齐 git 标签发布顺序时特别省事。如果你的版本号格式还不统一,可以先用 JSON 格式化工具 把依赖文件理清,再逐项核版本。

小结

记住三件事:主版本破坏兼容、次版本加功能、补丁修 bug;比较时每段都按整数读,不是按字符;预发布版排在正式版之前,构建元数据不参与比较。范围符号 ^~ 分别圈出不同宽窄的可升级区间。把这套规则吃透,再配上一个靠谱的比较器,依赖升级这件事就从靠猜变成有据可查。


Made by Toolora · Updated 2026-06-13