Semantic Versioning

30th September 2019 at 10:37am
Miscellaneous Node.js: Packaging

Semantic Versioning

这篇文章中讨论的 Semver 版本为 2.0.0,同时讨论了 npm 对 Semver 的使用。

目的

Semantic Versioning 的作用就是它名字所说,语义化的版本号。它定义了 MAJOR, MINOR, PATCH 三个部分,用来表示不同的含义:

1. MAJOR version when you make incompatible API changes,
2. MINOR version when you add functionality in a backwards-compatible manner, and
3. PATCH version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

他的意义是使开发者对它的项目中所使用的软件包版本号有一个把握。比如我有个项目 A 依赖项目 B,我在我的项目元信息文件中写入 B 的版本信息:

  • 如果我写死了 B 的版本号,那么 B 如果有 bug fix 版本发布时,我也得更新我所使用的 B 的版本号,同时发一个新版让我的用户也更新到
  • 如果我不想 B 发新版本我就得跟着发,那么我可能指定了 B 使用 [1.2.0, 2.0.0) 版本;但是假如 B 不遵循 Semver,那我不知道 B 会不会在 1.3.0 中引入了新的代码,把能在 1.2.0 中正常运行的代码搞挂了

表达得不太好,可以看看官方文档是怎样描述的。

规则

一条 Semver 分成这几部分:

<normal_version>[-<pre_release_version>][+<build_metadata>]

1.0.1-alpha.1+20160822

  • normal_version<major>.<minor>.<patch> 三部分组成,这三部分都必需是数字
  • pre_release_version 是由 . 号连接起来的一串字符串,. 分隔的每一部分的字符都需要是 [0-9a-zA-Z-]
  • build_metadata 是一个字符串,里面的字符需要是 [0-9a-zA-Z-]

比较时的规则:

  • 两个版本号先比较 normal version,每一部分依次按数字大小进行比较:1.9.0 < 1.10.0
  • pre-release 版本永远比同样的正常版本低优先:1.9.0-alpha < 1.9.0
  • normal version 相同时,比较 pre-release version:1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0
  • build metadata 部分不参与优先级比较

npm 处理 semver

npm 使用 semver 的主要场景是:

  1. npm install 命令行时指定版本号:
    1. npm install [<@scope>/]<name>@<version>
    2. npm install [<@scope>/]<name>@<version range>
  2. package.json 里指定版本号,最终被 npm install 解析

npm 的 semver 模块定义了一些操作符。常规的操作符 <, <=, =, >, >=。其中 = 操作符是可以省略的,比如 =1.7.0 与直接用 1.7.0 是等价的。

如果需要多个条件做 AND 逻辑,可以直接用空白字符分隔:>=1.9.0 <2.0.0;如果需要做 OR 逻辑,用 ll 操作符:1.7.0 || >=1.9.0 <2.0.0

还有一些高级的语义:

Hyphen Ranges:

  • 1.2.3 - 2.3.4 := >=1.2.3 <=2.3.4
  • 1.2 - 2.3.4 := >=1.2.0 <=2.3.4
  • 1.2.3 - 2.3 := >=1.2.3 <2.4.0
  • 1.2.3 - 2 := >=1.2.3 <3.0.0

X-Ranges:

  • * := >=0.0.0 (Any version satisfies)
  • 1.x := >=1.0.0 <2.0.0 (Matching major version)
  • 1.2.x := >=1.2.0 <1.3.0 (Matching major and minor versions)

A partial version range is treated as an X-Range:

  • "" (empty string) := * := >=0.0.0
  • 1 := 1.x.x := >=1.0.0 <2.0.0
  • 1.2 := 1.2.x := >=1.2.0 <1.3.0

Tilde Ranges ~1.2.3 ~1.2 ~1:应该是比较常用的,可以用来你需要的 major.minor 版本,这样你的代码一般不会因为 minor / major 的版本升级而挂掉。具体规则就不贴出来了。

Caret Ranges ^1.2.3 ^0.2.5 ^0.0.4:在项目还是 0.x 的情况下,小版本的变化往往被视为 breaking change。这个操作符是用来在依赖库为 0.x.x 情况下保证你的代码不挂掉的。

参考文献

  1. Semantic Versioning 2.0.0
  2. npm Semver document