语义化版本(SemVer)
什么是 SemVer
由于软件开发中会依赖各式各样的依赖库(包),随着数量的增多,以及版本的不断迭代,项目管理者必然面对这样的问题:如何正确的管理这些包的版本?
那通过什么来约定呢?所以就有了 SemVer:
SemVer(Semantic Versioning),语义化版本控制。
SemVer 通过不同的语法规则来约定不同版本间的升级方案,最终使得我们可以“随心所欲”的更新版本。
比如,前端项目 package.json 中包版本定义就是基于 SemVer 规范(npm 中实现了它):
1 | { |
下面就来看看这些语义化规范和语法规则。
语义化规范
为了下面能更好的理解规则,首先了解下相关语义化的含义:
版本号格式
1 | X.Y.Z; //主版本号.次版本号.修订号 |
标准的版本号必须为 X.Y.Z 的格式,且都为非负的整数。禁止数字前面补零(比如:02)
X 是主版本号(major version)、Y 是次版本号(minor version)、而 Z 为修订号(patch version)
版本只能每次 +1 的往上自然增加(比如:1.9.0 -> 1.10.0 -> 1.11.0)
另外,还有一些先行版版本号:
1 | X.Y.Z-alpha.1 |
约定先行版本号是在修订版之后,先加上一个连接号再加上一连串以句点分隔的标识符来修饰。
标识符必须由 ASCII 字母数字和连接号 [0-9A-Za-z-] 组成。比如:1.0.0-alpha、1.0.0-alpha.1、1.0.0-0.3.7、1.0.0-x.7.z.92。
更新 X、Y、Z 的场景
修订号 Z(patch version)
必须做向下兼容的修复时才递增(例如:修复 bug)
次版本号 Y(minor version)
必须向下兼容的新功能出现时递增,当某些功能被弃用也必须递增;
另外,当有大量新功能和改动时,也可以递增此版本号。
注:每次递增,修订号必须归零。
主版本号 X(major version)
必须在有任何不兼容的修改被加入公共 API 时递增。
注:每次递增,次版本号和修订号必须归零。
规则说明
一般规则
- <2.0.0 小于某版本
- <=2.0.0 小于 or 等于某版本
- >2.0.0 大于 or 等于某版本
- >=2.0.0 大于 or 等于某版本
- =2.0.0 精确等于某版本
上面这些规则都很好理解,简单看下下面例子:
1 | { |
那么执行 npm install 后,我们将准确得到版本为 2.20.0 的 moment 包,
以及最接近 0.19.4 版本为 0.19.2 axios 包
你有可能会问为什么不是 0.19.3?
我们可以通过 npm view 来查询有关 axios 所有的版本:
1 | npm view axios versions |
1 | [ |
能看到压根没有 0.19.3,直接跳到了 0.20.0-0。
高级规则
实际开发中,我们更多的是见到以下这些规则:
破折号策略(-)
1 | 1.2.3 - 2.3.4 // 代表 >=1.2.3 <=2.3.4 之间的版本,包含左右版本。 |
如果起始版本(左侧的版本)有空缺,将以 0 补位:
1 | 1.2 - 2.3.4 // 代表 >=1.2.0 <=2.3.4 |
如果结尾版本(右侧的版本)有空缺,将以 0 补位,并且递增非 0 版本号作为最大版本号:
1 | 1.2.3 - 2.3 // >=1.2.3 <2.4.0 |
泛版本策略(*)
可以使用 X, x, or * 来作为某个版本号的占位符,来示意所有可能的版本号。
1 | * // 代表 >=0.0.0 (所有版本) |
如果我们版本号有缺损,将为我们自动以占位符填充:
1 | "" (empty string) // 代表 * 即 >=0.0.0 |
波浪策略(~)
当前版本号为起始版本,以倒数第二个版本号+1(次版本号 Y)为递增版本,可更新 [起始,结束) 范围内的所有版本号。
如有版本号有空缺,将自动补 0,并以最近的空缺版本之前的版本号+1 作为递增的最大版本号。
对于 0.Y.Z 的开发阶段的版本号,将递增 0 后面的版本号作为递增的最大版本号。
1 | ~1.2.3 // 代表 >=1.2.3 <1.(2+1).0 即 >=1.2.3 <1.3.0 |
倒三角策略(^)
更新主版本号,如果版本号为 0,则往下取非 0 版本号递增,作为最大版本号。
1 | ^1.2.3 // 代表 >=1.2.3 <2.0.0 |
对于泛版本,以及空缺版本的示例:
1 | ^1.2.x // 代表 >=1.2.0 <2.0.0 |
1 | ^1.x // 代表 >=1.0.0 <2.0.0 |
最后
这篇只是简单说下 package.json 中版本号的更新规则,或许你每次 install 后从不关心版本升级策略,但随着项目功能迭代的增多,总会遇到团队某个开发人员安装了某个包后用了新特性,但在你的电脑上频繁报错。
可能你会在依赖包中“锁定”版本,但我们不能因噎废食,尽可能依靠灵活的版本升级策略,依靠社区为我们项目提供“生命力”。