发 npm 包对于略微大点的厂来说都是个频繁需要,因而本地执行计算版本命令以及 npm publish
都是不大可行的,大都会有一个独自的部署零碎去主动帮忙咱们实现这个事件。
明天就来聊聊这个部署零碎中外围的计算版本以及公布的逻辑以及流程。
Semver 语义化版本
聊部署零碎之前,咱们先得来聊聊语义化版本,因为笔者发现很多人对于这一块内容还是只知其一; 不知其二。
版本含意
- 小于 1.0.0:测试版,阐明该库目前 API 不稳固
- 大于等于 1.0.0:正式版
-
版本中携带 alpha、beta、rc 等 tag 字样,统称后行版,个别格局为 x.y.z-[tag].[次数 / meta 信息]
- alpha:外部版本
- beta:公测版本
- rc:预发的正式版本
版本号格局
个别的版本号格局都为 X.Y.Z,别离的含意为:
- X:major,主版本号,当有不兼容的 API 呈现时应该批改该版本号
- Y:minor,次版本号,当有向后兼容的新性能呈现时应该批改该版本号
- Z:patch,补丁,当须要修复向后兼容的 bug 时应该批改该版本号
然而这个语义也不是变化无穷的。比方当版本号为测试版时(版本小于 1.0.0 时),咱们能够将语义批改为 0.minor.patch
。因为此时呈现不兼容 API 是很失常的事件,不应该间接改变主版本号,而是应该改变次版本号,同时将性能新增及 bug 修复造成的版本变更体现在补丁上。
版本变更规定
X.Y.Z 必须为正整数且后面不能补零。
X.Y.Z 在每次变更版本号时,须要重置更小的版本号至 0。比如说 1.0.2 降级至 1.1.0。
同一个版本的后行版屡次公布,只需变更开端的次数或者 meta 值。比如说 1.0.0-beta.0 再次公布后行版应为 1.0.0-beta.1。
测试版个别从 0.1.0 开始计算。正式版个别在完结疾速迭代以及开发者认为 API 稳固当前就能够公布。
主动计算版本的前提条件
术语解释
npm 我的项目分为两种包构造:
- 单包,一个我的项目中只存在一个须要公布的 npm 包
- 多包,一个我的项目中存在多个须要发包的 npm 包,通常应用 lerna 治理
内容
如果咱们须要实现主动发版,就得让服务晓得咱们到底是须要发什么版本,否则无论怎样都不可能实现主动计算版本的需要。
因而咱们须要引入 commitizen 这个工具。
这个工具能够帮忙咱们提交规范化的 commit 信息:
格局如下:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
个别对于日常开发来说没那么谨严,type、description 必填,breaking 在须要的时候抉择,其余内容可有可无。
未免读者不明确这三者别离代表什么,笔者先来解释下
type 就是本次 commit 所做的代码变动,根本分为以下几种:
- feat:新个性,能够造成正式版变更次版本号
- fix: 批改 bug,能够造成正式版变更补丁版本号
- refactor: 代码重构,不会引起版本变更
- docs: 文档相干,不会引起版本变更
- style: 代码格局批改,不会引起版本变更
- test: 测试用例,不会引起版本变更
- chore: 工程配置相干的批改,不会引起版本变更
当然如果用户有个性化需要的话,也是能够增删这部分内容的。
description 就是字面意思了,代表本地 commit 的信息。
最初是 breaking,当有不兼容的 API 呈现时咱们须要提交这部分的内容,告知正式版须要变更主版本号。
PS:上文中说的都是正式版,如果以后版本为测试版的话,变更版本规定参考 版本变更规定大节。
最初生成进去的内容大抵长这个样子:fix: do not alter attributes
。
另外还有一个留神点是多包的问题。如果发版用对立版本的话事件就根本回归到单包构造上了,很简略。然而如果版本不对立的话,咱们就须要收集到底有哪些包是变更过文件的,在部署时只对变更过的包进行操作。
这里大抵有两种办法能够实现:
第一种办法是 @lerna/changed,这个工具能够帮忙咱们找到所有变更过的二方包。这里原理其实挺简略的,外围就是通过 git command 去实现:
git diff --name-only {git tag / commit sha} --{package path}
翻译过去就是寻找从上次的 git tag 或者首次的 commit 信息中查找某个包是否存在文件变更。
第二种形式能够革新 git cz 工具,新增一个性能:每次提交的时候主动带上本次提交变更了哪些包,当然底下还是用了下面的原理,然而咱们能够依据需要来定制更多的性能,更自在。
规范化的 commit 信息是主动部署零碎的基石,无论用工具也好还是间接手写,同时也能让开发者清晰地理解大抵我的项目做了哪些变更。
部署零碎中如何计算版本
计算版本是个挺乏味的货色,这里咱们须要用到 semver 来帮忙咱们计算,当然多包场景下你也能够应用 lerna 计算,然而咱们外部还是间接对立都 semver 算了。
另外算版本这件事件须要分场景来论,接下来咱们一个个来看。
当然在开始之前,咱们须要理解下版本的通用变更规定,因为几个场景都基于这个通用规定。
通用变更逻辑
首先来介绍下升版本所须要用到的几种类型:
major | minor | patch | premajor | preminor | prepatch | prerelease
前三种之前就聊过,这里不再多说。
之后三种都对应后行版,以 beta 版本举例 premajor,能将版本 1.0.0 变更为 2.0.0-beta.0,其实大体上还是和前三者雷同,无非多了一个后行版本号。
最初种同样也是对应后行版。以 beta 版本举例,能将版本 1.0.0 变更为 1.0.1-beta.0,同时也能将版本 1.0.1-beta.0 变更为 1.0.1-beta.1。
晓得了变更版本类型,咱们就该想该如何得出它们了。一般来说用户都会提交多个 commit,咱们首先须要找出其中所有的 commit type 并且取出一个最大值。
比如说用户自上次发版以来共提交了三个 commit,类型别离为 feat、doc、breakchange,那么最大类型为 breakchange。
得出最大 commit type 后,咱们须要依据不同的版本来计算。比如说正式版与测试版发版规定就不同,详见 版本号格局,不再赘述。
举个例子,以后版本为 1.0.0,此时依据 commit 咱们得出最大 type 为 feat,且须要公布后行版(beta),因而最终计算得出的变更规定为 preminor,可将版本升级为 1.1.0-beta.0。
剖析 commit 信息
上文有说到咱们须要剖析 commit 来获取 type,那么读者可能会疑难如何剖析?
其实原理很简略,还是用到了 git command:
git log -E --format=%H=%B
对于以上 commit,咱们能够通过执行命令得出以下后果:
当然这样剖析是把以后分支的所有 commit 都剖析进去了,大部分发版时候咱们只须要剖析上次发版至今的所有变更,因而须要修改 command 为:
git log 上次的 commit id...HEAD -E --format=%H=%B
最初就是各种正则表达式大显神通的时候了,想拿啥信息匹配就行。
单包场景
单包场景其实是最简略的,间接套用通用变更逻辑就行。
多包场景
单纯的多包环境其实也是简略的。无非比单包多了一步须要先找到哪些文件被变更了,而后须要筛选出 commit 中对应以后包的 type,最初就是套用通用变更逻辑。
多包且互有依赖场景
先解释下这个场景,比如说目前保护了 A、B、C 三个包,A 包的 dependencies 中蕴含了 B 和 C,这就是有依赖的意思,此时计算版本还须要多个步骤。
当通用逻辑完结当前,咱们须要依据依赖关系来判断是否还须要变更包版本。
比如说本地提交须要执行 patch 变更 B 包版本,其它两包都没有代码变动。然而实际上咱们还须要变动 A 的版本,否则光升 B 不升 A,用 A 包的用户就用不到 B 包的新版本变动了。
收尾
当咱们将所有版本计算结束当前,就须要写入 package.json 而后 执行 npm publish
,最初还须要提交下代码打上 tag。
最初
本篇文章就是大抵聊了下算版本以及公布这部分的内容,大家有问题的能够交换探讨。
另外我置信必定有读者会说这做的太麻烦,有别的工具能够简化步骤。这个笔者当然也晓得,然而他们底下主动批改版本的原理都是和本文统一的,理解下工具底下是怎么做事的也不为过。