【一库】semver:语义版本号标准 + npm的版本控制器🧲

6,766 阅读7分钟

📖阅读本文,你将:

  • 深入理解 npm 正在使用的 semver 语义版本号标准。
  • 学会使用一种版本号管理工具。

一、如果 没有了版本

版本是组件的 核心属性

让我们试想一下,如果没有版本 ,前端开发的场景会变成怎样什么样?

开始脑补:(没有了 版本 的前端开发)

  • npm install 永远会安装最新版本的依赖,上一秒正常运行的项目,在 npm install 后突然发现 api 失效了。install 变成了一个高危操作。

  • vue.jsissues 区里充满了这样的帖子:“无耻老贼,你怎么又把 alpha 版本发到 npm 上了?害我失业!”

  • vue.js 的官网上常年挂着一堆下载链接:“2022年7月18日下载包”、“2022年7月19日下载包”、“2022年7月19日紧急修复版”……

  • 办公室里,A同事对B同事喊了一声:“王哥,你那儿有上个月25号的vue版本不?用U盘拷我一分呗……”

  • 很多程序员下载 vue.js 选择去某“华军软件”下载,结果被捆绑了 360 全家桶……

  • 掘金社区天天有人发帖:“跪求支持 xxxx 的老版 vue ……”

  • 掘金网友 “摸鱼的春哥” 打包出售近三年所有发布过的 vue.js dist 文件,实现财务自由……

emmm……画风越来越奇怪,不禁让我们感慨,现如今的 npm 版本机制实在是太重要了,如果没有它,我们会分分钟退回刀耕火种的岁月。

那么,npm 的版本究竟是怎么玩转的呢?你又是否已经完全理解了 npm 版本所代表的含义呢?

不妨试试回答以下几个问题:

  • ^1.1.0~1.1.0 的区别是什么?
  • 1.01.02 是否合法?
  • 1.0.11.0.1-alpha.21.0.1-rc.2 这三个版本号由大到小的顺序是什么?
  • vue@latest 应该命中哪个版本?由谁决定?那么 vue@v2-beta 呢?

如果回答不上来,或者还心有疑虑,那么不妨继续看下去,寻找答案。

二、什么是 semver

我们常说的 semver 分为两个维度:

三、semver 标准

semver 有一套关于版本号的语义标准。

3.1 标准版本号(Major.Minor.Patch)

比如 16.7.1 这个简单的版本号,其实是由三个部分组成的:

  • 16 是它的 Major,主版本号,通常只有在重构、API不向下兼容时才会进行升级。
  • 7 是它的 Minor, 次版本号,通常在增加向下兼容新特性时升级此版本号。
  • 1 是它的 Patch,修订号,通常在发布向下兼容的问题修复时更新。

npm 指令集中,你可以通过指令来修改版本号,假设你现有一个 1.2.3 版本的项目。

通过执行指令,项目版本会直接发生变化

npm version major
# 1.2.3 => 2.2.3

npm version minor
# 1.2.3 => 1.3.3

npm version patch
# 1.2.3 => 1.2.4

3.2 先行版本号(pre-release)

上一节的 “标准版本号” 通常是指正式发布的版本。

但开发过程,往往还伴随着 内测公测生产候选 等种版本形式。

于是,在 “标准版本号” 的基础上又增加了一个新的版本号区域:pre-release 区。

如图所示。

先行版本号的典型格式是 -alpha.1 这样的形式,它由 一个短横线 + 一个字符串组成。

  • 短横线: -
  • 字符串:由大小写的字母、数字、句点 组成。

因此,以下先行版本号都是合法的:

  • 16.7.1-1
  • 16.7.1-a.2
  • 16.7.1-a.c

有一个经常被人弄错的知识点:16.7.1-alpha.1 的版本号是 小于 16.7.1

因为 16.7.1-alpha.116.7.1 的内测版本,所以它一定是小于正式版本的。

3.3 先行版本的约定命名

虽然 16.7.1-116.7.1-a.2 也是合法的 先行版本号 ,但大家一般不这么玩,倒不是规范不允许这么玩,而是它们的 语义化不优秀

因而,大家约定俗成了三个常见的 先行命名 方式,他们是:

  • 16.7.1-alpha.116.7.1 内测的第一个版本
  • 16.7.1-beta.116.7.1 灰度测试的第一个版本
  • 16.7.1-rc.116.7.1 生产候选的第一个版本

因为 r > b > a,所以这个约定实际也能代表上线的先后顺序:

16.7.1-alpha.1 < 16.7.1-beta.1 < 16.7.1-rc.1 < 16.7.1

同样的,npm version release 可以帮助你递增 先行版本号

四、npm 的版本匹配策略

4.1 模糊匹配符

npm 工程们并不永远精准的确认自己依赖哪一个版本,因为这会给你的应用带来过高的体积负荷。

假想一下:

  • A 组件声明它依赖 lodash@1.0.1 版本;
  • B 组件声明它依赖 lodash@1.0.2 版本;
  • C 组件声明它依赖 lodash@1.0.3 版本;

这样一来,你的工程里就不得不安装三个相近的版本,甚至导致你最终的 dist 文件里被打包了三份 lodash

这显然并不划算,更优秀的玩法是:只要 lodash 的版本号大于等于 1.0.1,且小于 2.0.0 都是满足需求的,因此组件们可以选择最大满足需求的范围来声明依赖版本。如:

三个库都只做如下声明:

依赖 lodash@^1.0.1

那么,程序就会找到 lodash 1.x版本中最新的一个版本,仅仅安装一次,也不会对后期构建产生冗余。

这种语法,就是 模糊匹配

  • ^1.0.111.x 代表了可以命中主版本一致、但更新的版本号。
  • ~1.0.11.11.1.x 代表了可以命中主版本、次版本一致、但更新的版本号。
  • *x 可以命中一切新发布的版本号。

4.2 dist-tag 和版本号

当你使用下面这条命令时,它应该命中哪个版本?

npm install vue@latest
# 或者换一句
npm install vue@next

从语义上,我们可以大抵理解:latest 是当前最新稳定版、next 则是最新下一代版本。

但它们又是怎么生效的呢?

这涉及到了一个 npm 指令:dist-tag

简单说:它可以支持你取一些 “别名标签”,并将它们和某个版本号关联起来。

比如,vue 这个众所周知的库就有9个 dist-tag:

  • beta : 灰度测试版本,当前匹配 3.2.34-beta.1
  • latest3.2.37 最新正式版
  • next3.2.36 下一代版本(在vue4出来前暂时没啥用了)
  • preview3.0.3 预览版
  • csp:内容安全版本
  • legacy:历史稳定版
  • v2-alphavue2 的内测版
  • v2-betavue2 的灰度版
  • v2-latestvue2 的最新正式版

因此,当你撰写自己的组件库时,别忘了通过以下命令标注出该工程的 latest 版本哦:

npm dist-tag add i-love-chunge@1.0.0 latest

这样一来,i-love-chunge@latest 就能命中 1.0.0 版本啦~

五、semver 标准的优秀实现:node-semver

5.1 node-semver 有什么用

用处很多:

  • 校验一个版本号是否合法。
    比如 1.2.3 合法;a.b.c 就不合法。

  • 比较两个版本号之间的大小。
    比如 1.2.3 就小于 9.8.7

  • 校验一个版本号是否命中了一个 “版本匹配规则”。
    比如 1.2.3 显然命中了 ^1.2.0 的规则。

  • 给一堆版本号进行排序

  • 对一个既有版本号进行升版

等等……

可以说,npm 所有关于 “版本号” 的操作逻辑,都可以通过 semver 来进行实现。

5.1 安装

通过 yarnnpm 等包管理工具都可以轻松安装。

npm install semver
# or
yarn add semver

然后通过以下命令进行引入即可:

const semver = require('semver')

5.2 使用

建议自行查看文档:github.com/npm/node-se…

  • 校验一个版本号是否合法:
semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
  • 清除版本号里一些多余的语句:
semver.clean('  =v1.2.3   ') // '1.2.3'
  • 比较版本号的大小
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true

因为文档上有,不做赘述,只要理解了 semver 标准,使用 node-semver 库将会非常顺畅。

如果未来你有关于版本号的校验逻辑,别忘了这个库哦~

六、结束语

我是春哥
大龄前端打工仔,依然在努力学习。
我的目标是给大家分享最实用、最有用的知识点,希望大家都可以早早下班,并可以飞速完成工作,淡定摸鱼🐟。

你可以在公众号里找到我:前端要摸鱼

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿