Semver(npm 语义化版本号)

简介

在软件管理的领域里存在着被称作“依赖地狱”的死亡之谷,系统规模越大,加入的包越多,你就越有可能在未来的某一天发现自己已深陷绝望之中。

在依赖高的系统中发布新版本包可能很快会成为噩梦。如果依赖关系过高,可能面临版本控制被锁死的风险(必须对每一个依赖包改版才能完成某次升级)。而如果依赖关系过于松散,又将无法避免版本的混乱(假设兼容于未来的多个版本已超出了合理数量)。当你专案的进展因为版本依赖被锁死或版本混乱变得不够简便和可靠,就意味着你正处于依赖地狱之中。

因此,Github 起草了一个具有指导意义的,统一的版本号表示规则,称为 Semantic Versioning(语义化版本表示)。该规则规定了版本号如何表示,如何增加,如何进行比较,不同的版本号意味着什么。

版本格式

版本格式:主版本号.次版本号.修订号,版本号递增规则如下:

  1. 主版本号:当你做了不兼容的 API 修改,
  2. 次版本号:当你做了向下兼容的功能性新增,
  3. 修订号:当你做了向下兼容的问题修正。

先行版本号及版本编译元数据可以加到主版本号.次版本号.修订号的后面,作为延伸。

先行版本

当要发布大版本或者核心的 Feature 时,但是又不能保证这个版本的功能 100% 正常。这个时候就需要通过发布先行版本。比较常见的先行版本包括:内测版、灰度版本了和 RC 版本。Semver规范中使用alpha、beta、rc (以前叫做gama)来修饰即将要发布的版本。它们的含义是:

  • alpha: 内部版本
  • beta: 公测版本
  • rc: 即Release candiate,正式版本的候选版本

比如:1.0.0-alpha.0, 1.0.0-alpha.1, 1.0.0-beta.0, 1.0.0-rc.0, 1.0.p-rc.1 等版本。alpha, beta, rc 后需要带上次数信息。

版本发布准则

列举出比较实用的一些规则:

  • 标准的版本号必须采用XYZ的格式,并且X、Y 和 Z 为非负的整数,禁止在数字前方补零,版本发布需要严格递增。例如:1.9.1 -> 1.10.0 -> 1.11.0。
  • 某个软件版本发行后,任何修改都必须以新版本发行。
  • 1.0.0 的版本号用于界定公共 API。当你的软件发布到了正式环境,或者有稳定的API时,就可以发布 1.0.0 版本了。
  • 版本的优先层级指的是不同版本在排序时如何比较。判断优先层级时,必须把版本依序拆分为主版本号、次版本号、修订号及先行版本号后进行比较。

npm包依赖

1
2
3
4
5
{
"dependencies": {
"react": "^15.6.1",
}
}

项目对包的依赖可以使用下面的 3 种方法来表示(假设当前版本号是 16.2.0):

  • 兼容模块新发布的补丁版本:~16.2.0、16.2.x、16.2
  • 兼容模块新发布的小版本、补丁版本:^16.2.0、16.x、16
  • 兼容模块新发布的大版本、小版本、补丁版本:*、x

^

允许在不修改 [major, minor, patch] 中最左非零数字的更改(匹配大于 X、Y、Z 的更新 Y、Z 的版本号)

在 X.Y.Z 结构的版本号中,X、Y、Z 都是非负的整数,上面定义的意思就是说从左向右,遇到第一个非零数字是不可修改的,下一个数字可以更改,比如:

  • X、Y、Z 都不为 0,^15.6.1,最左的非零数字是15,所以 X 是不允许更新的,也就是说主版本号不会超过15,表示的就是版本号>=15.6.1 && <16.0.0
  • 如果 X 为 0,那么第一个非零数字就是 Y,就只能对 z 做出修改,^0.1.2表示版本号>=0.1.2 && < 0.2.0
  • 如果 X、Y 的数字都是 0 的话,第一个非零数字就是 Z,表示的就是版本号不允许更新;^0.0.2,主版本号和次版本号都是 0,修订号为非零,表示的就是版本号>=0.0.2 && < 0.0.3

~

匹配大于 X.Y.Z 的更新 Z 的版本号

  • X、Y、Z 都不为 0,~1.2.3 表示版本号 >=1.2.3 && < 1.3.0
  • X 为 0,~0.2.3 表示版本号 >=0.2.3 && < 0.3.0,这种情况下,~ 等价于 ^
  • X、Y 为0,0.0.3 表示版本号 >=0.0.3 && < 0.1.0

x

可以替代 X、Y、Z 中任意一个,表示该位置可更新

  • 1.2.x: >=1.2.0 && < 1.3.0
  • 1.x: >=1.0.0 && < 2.0.0
  • *: 任意版本都可以

上面的 x 可以用 * 代替,其实,用 x* 的地方可以省略不写,比如 1.2.x1.2 表示的意思是一样的

npm包发布

通常我们发布一个包到 npm 仓库时,我们的做法是先修改 package.json 为某个版本,然后执行 npm publish 命令。手动修改版本号的做法建立在你对 Semver 规范特别熟悉的基础之上,否则可能会造成版本混乱。npm 考虑到了这点,它提供了相关的命令来让我们更好的遵从 Semver 规范:

  • 升级补丁版本号:npm version patch
  • 升级小版本号:npm version minor
  • 升级大版本号:npm version major

当执行 npm publish 时,会首先将当前版本发布到 npm registry,然后更新 dist-tags.latest 的值为新版本。
当执行 npm publish --tag=next 时,会首先将当前版本发布到 npm registry,并且更新 dist-tags.next 的值为新版本。这里的 next 可以是任意有意义的命名(比如:v1.x、v2.x 等等)

参考