如何使用工具规范前端项目的 commits & changelog
项目的 Changelog 文件作为记录版本之间的差异和变更的主要“公示板”,主要用于传达一些关键的变更和指南,是直接与使用者对话的一种形式,所以 changelog 文件的整洁、直观一直是衡量一个项目质量的重要指标。
而且在我们翻阅一些组件库或者开源框架的 changelog 变动页的时候,经常看到一些项目的整齐、直观、井井有条如下面示例。这样的 log 日志必然不是手动排版出来的,大部分都是根据 commit 的描述自动生成的。
那么它们是如何配置,或者使用了什么工具包呢?想必大家都比较好奇。接下来我们就来一步一步揭开它神秘的面纱,并一步步的配置我们的组件库的 commit 规范,使我们的 commit 和 changelog 文件也能如此优雅。
示例一:semi 的 changelog 文件
示例二:antd 的 github changelog
Conventional Commits 规范
要保持 commit 信息的可读性,一个合理的 commit 格式规范是必不可少的,而 Conventional Commits 就是一种基于提交消息的轻量级约定。官方是这样描述它的:
它提供了一组用于创建清晰的提交历史的简单规则; 这使得编写基于规范的自动化工具变得更容易。 这个约定与SemVer相吻合, 在提交信息中描述新特性、bug 修复和破坏性变更。 --- Conventional Commits 官网
由此可以看出 Conventional Commits 是一个非常友好且清晰的规范,那遵循它的好处有哪些? 我们来进行一个总结:
- 可格式化信息,自动产生 changelog;
- 校验拦截不符合规则的 commit 描述;
- 根据类型决定当前版本变更的性质;
- 统一提交信息,有利于代码审查者的阅读。
那么 Conventional Commits 规则到底是如何的呢,我们接着往下看。通过官网的文档可以发现,它提交说明的结构如下所示:
<类型>[可选的作用域]: <描述>
[可选的正文]
[可选的脚注]
举例:
fix(docs): 修复文档中字符错误
feat(components): tooltip 组件初始化
可以看到,结构里面包含类型、作用域、描述、正文、脚注。
- 类型:用来标示当前提交是一个什么样的类型,比如最常见的有
fix
、feat
等,用来标示当前的提交是一个修复类的操作,或者一个新功能的增加。可枚举的类型还有:chore
、docs
、style
、refactor
、perf
、test
等。这块可以参照 @commitlint/config-conventional 里面的枚举值。
- 作用域:此字段可自行定义枚举值,根据业务模块划分即可,比如:当前是【文档】的改动就可以填写 docs;当前影响了 utils 库,就可以填写 feat(utils):等等,取值不限制。
- 描述:描述就是对当前 commit 的简短描述,尽量简短,清晰。
- 正文:对于简短描述的扩充填写,可选。
- 脚注:包含关于提交的元信息,比如:有关联的请求url、cr人员、等等一些关键性信息。
- 特别需要注意的是:在可选的正文或脚注的起始位置带有
BREAKING CHANGE:
的提交,表示引入了破坏性 API 变更(这和语义化版本中的MAJOR
相对应)。 破坏性变更可以是任意类型提交的一部分。
可以看出 Conventional Commits 规范非常高效且上手难度很低,并且 Conventional Commits 已经被很多知名的开源项目所集成,是一个被大家广泛接受的标准。而我们的组件库也需要遵循它来规范我们的 commit。
要如何遵循此规范呢?用插件来约束我们的 commit 是一个比较好的解决方案。接下来,我们来看下有哪些插件可以让我们愉快的使用。
哪些工具可以组合起来规范我们的 commit?
Commitizen
上面我们说到了 Conventional Commits 规范,我们要遵循此规范时,可能手动去处理 commit 信息会比较繁琐,并且出错率也很高,比如在我们书写 fix(scope): xxx 时,很容易对于符合的全角还是半角输入法搞混,这样很容易造成信息格式化的失败。那么我们该如何高效稳定的遵循 Conventional Commits 规范呢?Commitizen 应声而来。
Commitizen 可以说是一个交互性日志提交工具,用于辅助开发者提交符合规范的 commit 信息。它可以说是提供了“保姆式”的提交体验,在我们触发 commit 的脚本后,只需要根据提示来选择我们的提交信息,就可以生成一个符合规范的 commit。
? Select the type of change that you're committing: (Use arrow keys)
❯ feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing tests or correcting existing tests
(Move up and down to reveal more choices)
cz-customizable
cz-customizable 作为一个用于自定义 Commitizen 的扩展插件,可以在原生 Commitizen 的标准上,根据配置文件来自定义我们的提交规范。可以说是用来扩展 Commitizen 的神器。一般都用于 Commitizen 的配套使用。
? 选择一种你的提交类型: (Use arrow keys)
❯ feat 🍄: 新增新的特性
fix 🐛: 修复 BUG
docs 📄: 修改文档、注释
refactor 🎸: 代码重构,注意和特性、修复区分开
perf ⚡: 提升性能
test 👀: 添加一个测试
tool 🚗: 开发工具变动(构建、脚手架工具等)
(Move up and down to reveal more choices)
commitlint
commitlint 用来校验检查我们的提交 commit 是否符合conventional commit format。类似于 eslint,commitlint 可以根据我们的配置文件或者默认的选项值来校验我们的 commit 信息,不通过的校验会被直接打回。
standard-version
standard-version 是一款遵循语义化版本(semver)和 commit message 标准规范的版本自动化工具,它还可以使生成 changelog 自动化。并且将我们符合 Conventional Commits 规范的提交信息格式化,并完成以下操作:
- 根据现在 package.json 文件中的 版本号 version 进行 commit 的整合。并更新 changelog 文件。
- 提交暂存文件 git add . 。
- git commit 。
- 打标签 git tag。
总体来说,它帮助我们自动化的进行了发版所需要的步骤,并且根据 commit 信息,生成 log 日志。这样我们就只需要专注于我们的逻辑开发,其他的都可以交给 standard-version 去完成。
以上是我们规范 commit 信息、根据提交的 commit 信息自动化更新 changelog、发版等一条龙服务所必须用到的插件。经过简单的熟悉后,我们来进行实际的配置,让我们组件库的 commit 优美起来。
安装配置
俗话说的好,动手是第一生产力。接下来我们将一步步安装配置我们的 commit 规范。
1. 安装 commitizen 和 cz-customizable
pnpm install -D commitizen cz-customizable
在最外层 package.json 文件中添加脚本命令和配置项,使 commitizen 使用cz-customizable 插件。
{
...
"scripts" : {
...
"commit": "git cz"
}
...
"config": {
"commitizen": {
"path": "cz-customizable"
}
}
}
接下来在根目录新建 .cz-config.js 文件,并加入我们的汉化配置。
// .cz-config.js module.exports = {
types: [
{ value: "feat", name: "feat 🍄: 新增新的特性" },
{ value: "fix", name: "fix 🐛: 修复 BUG" },
{ value: "docs", name: "docs 📄: 修改文档、注释" },
{ value: "refactor", name: "refactor 🎸: 代码重构,注意和特性、修复区分开" },
{ value: "perf", name: "perf ⚡: 提升性能" },
{ value: "test", name: "test 👀: 添加一个测试" },
{ value: "tool", name: "tool 🚗: 开发工具变动(构建、脚手架工具等)" },
{ value: "style", name: "style ✂: 对代码格式的修改不影响逻辑" },
{ value: "revert", name: "revert 🌝: 版本回滚" },
{ value: "update", name: "update ⬆: 第三方库升级 " }
],
scopes: [{ name: '组件' }, { name: '样式' }, { name: '文档更改' }, { name: '其它变更' }],
allowTicketNumber: false,
isTicketNumberRequired: false,
ticketNumberPrefix: 'TICKET-',
ticketNumberRegExp: '\d{1,5}',
messages: {
type: "选择一种你的提交类型:",
scope: "选择一个scope (可选):",
customScope: "Denote the SCOPE of this change:",
subject: "简要说明:\n",
body: '详细说明,使用"|"换行(可选):\n',
breaking: "非兼容性说明 (可选):\n",
footer: "关联关闭的issue,例如:#31, #34(可选):\n",
confirmCommit: "确定提交?"
},
allowCustomScopes: true,
allowBreakingChanges: ['新增', '修复'], subjectLimit: 100 };
配置好后我们先进行测试:npm run commit
,得出下面结果:
All lines except first will be wrapped after 100 characters.
? 选择一种你的提交类型: (Use arrow keys)
❯ feat 🍄: 新增新的特性
fix 🐛: 修复 BUG
docs 📄: 修改文档、注释
refactor 🎸: 代码重构,注意和特性、修复区分开
perf ⚡: 提升性能
test 👀: 添加一个测试
tool 🚗: 开发工具变动(构建、脚手架工具等)
说明配置完成,我们可以接着往下进行。
2. 安装 commitlint
pnpm install -D commitlint-config-cz @commitlint/cli yorkie
在 package.json 中的 husky hook 中添加每次 commit 信息的校验回调。
ps:没有安装 husky 的先自行安装 pnpm install -D husky
{
"husky": {
"hooks": {
"commit-msg": "commitlint -e -V",
}
}
}
在根目录构建 commitlint.config.js 文件,进行 commitlint 的配置。
module.exports = {
extends: ['cz'],
parserPreset: {
parserOpts: {
headerPattern: /^(.*?)((.*?)):\s?(.*)$/,
headerCorrespondence: ['type', 'scope', 'subject'],
},
},
rules: {
'type-empty': [2, 'never'],
'subject-empty': [2, 'never'],
},
};
接下来我们实验一下,提交一个空内容。
? 选择一种你的提交类型: feat 🍄: 新增新的特性
? 选择一个scope (可选): 其它变更
? 简要说明:
➜ sten-design git:(master) ✗ git commit -m 'feat'
husky > commit-msg (node v14.17.0)
⧗ input: feat
✖ type may not be empty [type-empty]
✖ subject may not be empty [subject-empty]
✖ found 2 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
husky > commit-msg hook failed (add --no-verify to bypass)
会报错,说明我们的 commitlint 已经生效。
3. 安装 standard-version
pnpm install -D standard-version
配置脚本。
// package.json
{
"scripts": {
"release": "standard-version"
}
}
增加 .versionrc.js 文件来格式化 log ,使我们的 changelog 根据 Conventional Commits 规范更加语义化。
module.exports = {
"types": [
{ "type": "feat", "section": "✨ Features | 新功能" },
{ "type": "fix", "section": "🐛 Bug Fixes | Bug 修复" },
{ "type": "init", "section": "🎉 Init | 初始化" },
{ "type": "docs", "section": "✏️ Documentation | 文档" },
{ "type": "style", "section": "💄 Styles | 风格" },
{ "type": "refactor", "section": "♻️ Code Refactoring | 代码重构" },
{ "type": "perf", "section": "⚡ Performance Improvements | 性能优化" },
{ "type": "test", "section": "✅ Tests | 测试" },
{ "type": "revert", "section": "⏪ Revert | 回退" },
{ "type": "build", "section": "📦 Build System | 打包构建" },
{ "type": "update", "section": "🚀 update | 构建/工程依赖/工具升级" },
{ "type": "tool", "section": "🚀 tool | 工具升级" },
{ "type": "ci", "section": "👷 Continuous Integration | CI 配置" }
]
}
先提交一个 commit 再测试:
然后我们再执行 yarn release
升级版本:
yarn run v1.22.11
$ standard-version
✔ bumping version in package.json from 0.0.1 to 0.0.2
✔ created CHANGELOG.md
✔ outputting changes to CHANGELOG.md
✔ committing package.json and CHANGELOG.md
husky > commit-msg (node v14.17.0)
⧗ input: chore(release): 0.0.2
✔ found 0 problems, 0 warnings
✔ tagging release v0.0.2
ℹ Run `git push --follow-tags origin master` to publish
✨ Done in 2.79s.
我们再看下 CHANGELOG.md 文件:
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.1.1]( https://github.com/fanshyiis/sten-design/compare/v0.0.8...v0.1.1) (2022-02-12)
### 🚀 tool | 工具升级
* **其它变更:** 测试 commit 信息 ([6446270](https://github.com/fanshyiis/sten-design/commit/64462708008fa863abcfc026191fe20499f586f8))
### ✨ Features | 新功能
* **组件:** 我是一个新功能 ([9b9d30f](https://github.com/fanshyiis/sten-design/commit/9b9d30f7bac36b9b8c6e4786be45031cea6bfba6))
和具体 Git 上展示效果:
总结
在 Conventional Commits 和一系列组件的约束下,可以使我们的 changelog 文件更加直观、优美。并且,全自动化的配置,也不需要我们过多的关注,只需要用心写好每一个 commit 的描述信息即可。
转载自:https://juejin.cn/post/7199250631114407995