1

介绍

前端开发的过程中需要引入一些第三方包,帮助我们快速高效地开发。当第三方包有修改,我们更新包的版本时,我们需要了解包修改的范围,以便对此做出相关反应。

为此,由 Gravatars 创办者兼 GitHub 共同创办者 Tom Preston-Werner 建立了语义化版本控制规范(Semantic Version),表现在 npm 包的版本号中。

单个版本号的构成

结构

major.minor.patch(-prerelease)?

  • major.minor.patch

    • 三者都为自然数;且都以数值来递增。
    • 正则表达:[1-9][0-9]*
  • prerelease

    • 在修订号之后,先加上一个连接号(-)再加上一连串以句号(.)分割的标识符([0-9A-Za-z-])来修饰。
    • 数字型的标识符,为自然数
    • 正则表达:-[0-9A-Za-z-](\.[0-9A-Za-z-])*

major(主版本号),minor(次版本号),patch(修订号),prerelease(先行版本号)

major.minor.patch 为标准版本号。

语义说明

  • major - 当包源代码修改,修改无法做到向下兼容时,主版本号递增;该修改,可以包含次版本号和修订号的情况。
  • minor - 当包源代码修改,新增一些向下兼容的功能,次版本号递增;该修改,可以包含修订号的情况。
  • patch - 当包源代码修改,做了向下兼容的问题修改,修订号递增。
  • prerelease - 被加上先行版本号表示该版本并非正式版,存在不稳定的情况。

大小比较

  • 标准版本比较:major.minor.patch

    • 从左往右,按照数值的大小比较,例如:1.0.0 < 2.0.0 < 2.1.0 < 2.1.1。
  • 先行版本比较:通过先行版本号中,从左往右的每个被句号分开的标识符来比较。

    • 只有 数字标识符 比较时,则按数值的大小比较。
    • 只有 非数字标识符 比较时,则按照 每个标识符每个字符 在 ASCII 中的顺序来比较。
    • 数字标识符非数字标识符 比较时,则 非数字标识符 优先级高。
    • 若每个标识符都相同的情况,则 标识符层级多 的先行版本号 优先级高
  • 混合比较

    • 带有 先行版本号 的版本优先级 低于 相关联的 标准版本 ,例如:1.2.3-beta-1 < 1.2.3

版本的顺序

version sort

版本号的范围

背景:为了解决在项目中同一个包不同版本的兼容需求,以及安装包时可以升级到预期的最新版本。version 字段可以表达一个版本的范围。

结构

版本范围(version range): (operator version)(joiner(operator version))*

比较器(comparator)结构为:(operator version)

初始操作符

  • <version: 小于某个版本
  • <=version: 小于或等于某个版本
  • >version: 大于某个版本
  • >=version: 大于或等于某个版本
  • =version: 等于某个版本;当没有操作符时,默认为等于(=)操作符,因此该操作符可以不用写。

例如:>=1.2.7,将匹配1.2.71.2.82.5.31.3.9,但不会匹配1.2.61.1.0

连接符(joiner)

  • 空格(whitespace):当比较器由空格连接时,相当于且(&&)。例如,>=1.2.7 <1.3.0,将匹配1.2.71.2.81.2.99,但不会匹配1.2.61.3.01.1.0
  • || :当比较器由 || 连接时,表示 “或“ 的意义。例如,1.2.7 || >=1.2.9 <2.0.0,将匹配 1.2.71.2.91.4.6,但不会匹配1.2.82.0.0
与 && 、 || 的优先级一样,空格的优先级高于 || 优先级。

先行版本号的范围

先行版本号的存在表示该版本为非正式版本,存在不稳定的情况。因此带有先行版本号的比较器,其版本覆盖范围有以下两点:

  1. 正式版本号的范围。
  2. 正式版本号的先行版本号的范围。

例如: >1.2.3-alpha.3 ,相当于 >1.2.3-alpha.3 <1.2.4-0 || >1.2.3 ;将匹配 1.2.3-alpha.73.4.5 ,但不会匹配 3.4.5-alpha.9

只有标准版本号的范围是无法匹配任何带有先行版本号的版本号,例如: >1.2.3 ,将匹配 1.2.4,但不会匹配1.2.4-alpha.9

高级版本范围语法

-(Hyphen Ranges)

结构: startVersion - endVersion 相当于 >=startVersion <=endVersion

意义:指定一个版本范围。

例如:1.2.3 - 2.3.4 相当于 >=1.2.3 <=2.3.4

在该语法下,如果版本号的结构中正式版本号部分有缺失,具体处理逻辑为:开始版本号、结束版本号,分别向两端延伸。

例如,开始版本号中的结构有缺失,补 0 处理:

  • 1.2 - 2.3.4 相当于 >=1.2.0 <=2.3.4

例如,结束版本号中的结构有缺失,补 X 处理:

  • 1.2.3 - 2.3 相当于 1.2.3 - 2.3.x 相当于 >=1.2.3 <2.4.0-0
  • 1.2.3 - 2 相当于 1.2.3 - 2.x.x 相当于 >=1.2.3 <3.0.0-0

X(X-Ranges)

Xx* 在正式版本号中表示为一个数字的占位符,意义为一个自然数。

  • * 相当于 >=0.0.0(任何版本都满足)
  • 1.x 相当于 >=1.0.0 <2.0.0-0(匹配主版本号)
  • 1.2.x 相当于 >=1.2.0 <1.3.0-0(匹配次版本号)

版本号中如有缺失部分,也被当作 X 看待,例如:

  • '' 相当于 *
  • 1 相当于 1.x.x
  • 1.2 相当于 1.2.x

~(Tilde Ranges)

具有完整版本号结构的前提下,允许修订号级别的升级变动。

例如:

  • ~1.2.3 相当于 >=1.2.3 <1.3.0-0
  • ~1.2.3-beta.2 相当于 >=1.2.3-beta.2 <1.3.0-0

其他情况,相当于补 X

  • ~1.2 相当于 1.2.x
  • ~1 相当于 1.x.x

^(Caret Ranges)

具有完整版本号结构的前提下,以标准版本号中最左侧第一个非零元素为界限,允许向后低级别元素的升级变动。

例如:

  • ^1.2.3 相当于 >=1.2.3 <2.0.0-0
  • ^0.2.3 相当于 >=0.2.3 <0.3.0-0
  • ^0.0.3 相当于 >=0.0.3 <0.0.4-0
  • ^1.2.3-beta.2 相当于 >=1.2.3-beta.2 <2.0.0-0

其他情况,相当于补 X

例如:
^0.x 相当于 0.x.x

正式版本之后, ^ 符号的版本范围等同于 主版本号 不改动, 次版本号修改号 可以任意升级变动。

修改版本号

npm CLI 提供了编辑和查看 version 的一系列命令。

查看版本号

npm view <pkg> version :查看某个 pkg latest 标签上的最新版本号。

npm view <pkg> versions :查看某个 pkg 所有发布过的版本号。

编辑版本号

编辑版本号是通过 npm version 命令来操作的。该命令在修改 package.json - version 的同时,也会自动执行 git commit 保存版本号至 git tag 。因此在操作该命令之前需要保证 git status 是 clear 的。

npm version <newversion>:newversion 会完全覆盖 package.json - version 的值。

npm version major:升级主版本号。

npm version minor:升级次版本号。

npm version patch:升级修订号。

npm version --preid=<prerelease-id>:为先行版本号设置一个语义化的前缀。例如,当前版本号为 1.0.1 ,执行 npm version --preid=alpha 之后,版本号变为 1.0.2-alpha.0

npm version prerelease:升级先行版本号;例如,当前版本号为 1.0.1-alpha.0 ,执行 npm version prerelease 之后,版本号变为 1.0.1-alpha.1,再执行 npm version prerelease 之后,版本号变为 1.0.1-alpha.2,以此类推。

最佳实践

开发初始阶段

npm 包的开发初始阶段版本号为:0.a.b,这一阶段的代码被认为不稳定的,还无法对外公布。

开发阶段的起始版本号可以为:0.0.0,也可以定为其他版本号, 没有限制。

先行版本号

在开发 npm包 的过程中需要经过一连串的测试环节,通常我们会看到三种类型的 prerelease,分别是:alpha、beta、rc,例如:

  • 1.1.0-alpha.0
  • 1.1.0-beta.0
  • 1.1.0-rc.0

每种类型的 prerelease 都有其特殊的含义:

  • alpha - 内测版本,一般为测试环节的第一步;该版本主要给开发人员和测试人员使用的。
  • beta - 公测版本,一般为测试环节的第二步;该版本主要给部分公测用户使用的。
  • rc(release candidate) - 候选版本,一般为测试环节的第三步;该版本对外公布,并且允许部分或者所有的用户使用;这个版本类似 预览版尝鲜版;该版本已经与正式版本非常接近了 。

在测试过程中,没有必要遵守上面三个测试步骤,开发者可以根据实际需要选择某个 prerelease 作为测试终结版本,并且对外发布相应的正式版本。例如:当 2.0.0-alpha-1 具备发布正式版的条件时,就可以对外发布 2.0.0 版本。

prerelease 版本号从 0 开始,例如:1.1.0-alpha.0

正式版本

正式版本发布的条件:初期开发阶段测试结束, npm包 具备对外公布的条件。

第一个正式版本的版本号为:1.0.0

从此便开始 npm包 的维护阶段,根据公共 API 及其修改内容更新版本号。

参考

  1. package-json#version
  2. semver
  3. node-semver
  4. NPM package 版本管理最佳实践 #2

Steven
38 声望3 粉丝