0
点赞
收藏
分享

微信扫一扫

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

📖阅读本文,你将:

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

一、如果 没有了版本 ?

版本是组件的 核心属性

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

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

  • ​npm install​​​ 永远会安装最新版本的依赖,上一秒正常运行的项目,在 ​​npm install​​ 后突然发现 ​​api​​ 失效了。​​install​​ 变成了一个高危操作。
  • ​vue.js​​​ 的 ​​issues​​ 区里充满了这样的帖子:“无耻老贼,你怎么又把 ​​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​​ 文件,实现财务自由……

【一库】semver:语义版本号标准 + npm的版本控制器?_前端

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

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

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

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

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

二、什么是 ​​semver​​ ?

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

  • 维度一:它是一套跨语言的语义化版本号标准。
    标准地址:​​semver.org/lang/zh-CN/​​
  • 维度二:是基于这套标准的实现,比如​​node-semver​​(​​npm​​ 就依赖着它)。 ​​npm​​ 的版本策略,几乎全部都由它进行控制 。
    npmjs:​​www.npmjs.com/package/sem…​​github:​​github.com/npm/node-se…​​

三、​​semver​​ 标准

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

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

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

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

  • 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​​ 区。

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

如图所示。

先行版本号的典型格式是 ​​-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.1​​​ 是 ​​16.7.1​​ 的内测版本,所以它一定是小于正式版本的。

3.3 先行版本的约定命名

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

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

  • ​16.7.1-alpha.1​​​ :​​16.7.1​​ 内测的第一个版本
  • ​16.7.1-beta.1​​​ :​​16.7.1​​ 灰度测试的第一个版本
  • ​16.7.1-rc.1​​​ :​​16.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​​。

【一库】semver:语义版本号标准 + npm的版本控制器?_前端_04

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

三个库都只做如下声明:

依赖 lodash@^1.0.1

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

这种语法,就是 模糊匹配

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

4.2 ​​dist-tag​​ 和版本号

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

npm install vue@latest
# 或者换一句

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

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

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

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

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

  • ​beta​​​ : 灰度测试版本,当前匹配​​3.2.34-beta.1 ​
  • ​latest​​​ :​​3.2.37​​ 最新正式版
  • ​next​​​ :​​3.2.36​​ 下一代版本(在vue4出来前暂时没啥用了)
  • ​preview​​​ :​​3.0.3​​ 预览版
  • ​csp​​:内容安全版本
  • ​legacy​​:历史稳定版
  • ​v2-alpha​​​:​​vue2​​ 的内测版
  • ​v2-beta​​​:​​vue2​​ 的灰度版
  • ​v2-latest​​​:​​vue2​​ 的最新正式版

因此,当你撰写自己的组件库时,别忘了通过以下命令标注出该工程的 ​​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 安装

通过 ​​yarn​​​、​​npm​​ 等包管理工具都可以轻松安装。

npm install semver
# or

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

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​​ 库将会非常顺畅。

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

六、结束语

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

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

举报

相关推荐

0 条评论