前端项目的提交规范
是前端基建
必备技能之一。下面介绍规范提交代码时会用到的工具,以及在常见场景中如何去使用。
Husky
Git hooks 管理工具。
允许开发者在项目中设置自定义的 Git 钩子脚本。
自动检查您的提交消息、代码,并在提交或推送时运行测试。
安装
js
npm install --save-dev husky
初始化
js
npx husky init
初始化成功之后,会在项目根目录下创建.husky
和.husky/_
文件夹,并创建钩子(git hooks)脚本,目录结构如下:
js
├─ .husky
│ ├─ _
│ │ ├─ .gitignore
│ │ ├─ applypatch-msg
│ │ ├─ commit-msg
│ │ ├─ h
│ │ ├─ husky.sh
│ │ ├─ post-applypatch
│ │ ├─ post-checkout
│ │ ├─ post-commit
│ │ ├─ post-merge
│ │ ├─ post-rewrite
│ │ ├─ pre-applypatch
│ │ ├─ pre-auto-gc
│ │ ├─ pre-commit
│ │ ├─ pre-push
│ │ ├─ pre-rebase
│ │ └─ prepare-commit-msg
│ └─ pre-commit
Git Hooks
名称 | 说明 | 使用场景 |
---|---|---|
applypatch-msg | 当从一个应用补丁中创建一个新的提交时运行 | 通常用于验证补丁消息格式 |
pre-applypatch | 在应用补丁到工作目录和索引前触发 | 可以用来阻止不满足条件的补丁被应用 |
post-applypatch | 补丁成功应用后执行 | 可以用于清理、通知或进一步处理 |
pre-commit | 执行 git commit 前触发 |
常用于运行代码风格检查(如 ESLint )、类型检查(如 TypeScript)或单元测试等,防止不符合规范的代码进入仓库。 |
prepare-commit-msg | 在编辑提交消息文件之前运行 | 可以自动生成(如:Commitizen )或修改默认的提交消息 |
commit-msg | 在提交消息写入磁盘之后,但提交实际发生之前执行 | 通常用于验证提交消息格式是否符合团队规范,可以结合工具如 Commitlint 来实现。 |
post-commit | 提交操作完成后立即触发 | 可用于执行发送通知、更新本地构建版本号或其他后提交的任务 |
pre-rebase | 在开始交互式 rebase 或自动 rebase 之前触发 | 可以用来禁止某些类型的 rebase 操作 |
post-checkout | 切换分支或者检出某个提交后执行 | 用于进行与当前工作目录状态相关的切换后的操作 |
post-merge | 合并操作完成后运行 | 可能用于重建项目依赖项、清理临时文件或触发自动化部署流程 |
pre-push | 在将本地提交推送到远程仓库之前执行 | 通常用于执行更全面的测试套件,确保即将推送的代码质量 |
pre-receive / update | 这两个钩子在远程仓库服务器上执行,而不是本地 | pre-receive 在接收推送前一次性运行,可以拒绝整个推送;而 update 对每个要更新的引用分别运行,允许对各个分支进行单独控制 |
Commitlint
用于验证 Git 提交消息格式是否符合预定义规范的工具,结合 Husky 工具来设置
commit-msg
钩子。
安装
@commitlint/config-conventional
是一个预定义的配置包,与@commitlint/cli
配合使用来验证 Git 提交消息格式是否符合 Conventional Commits 规范。
js
npm install --save-dev @commitlint/cli @commitlint/config-conventional
配置
在根目录下创建commitlint.config.js
,并配置:
js
// commit-lint config
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test', 'types'],
],
},
};
常用配置Api
名称 | 说明 | 使用场景 |
---|---|---|
extends | 扩展默认规范 | @commitlint/config-conventional |
rules | 校验规则 | - 错误级别(severity level):0(禁用)、1(警告)、2(错误) - 规则应用情况(when):通常是 'always' 或 'never' - 规则值(value):根据具体规则而定,可以是字符串、数组或其他形式的数据结构 |
rules.type-enum | 确保提交消息中的类型字段(type)在预定义的枚举列表中 | { "type-enum": [2, "always", ["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test", "types"]]} |
rules.subject-case | 检查提交消息主题(subject)的大小写风格 | {"subject-case": ["2", "always", "lower-case"]} |
rules.scope-enum | 限制提交消息中的作用域(scope)只能是预先定义的值之一 | {"scope-enum": ["2", "always", ["core", "ui", "api"]]} |
rules.subject-full-stop | 控制提交消息的主题行末尾是否需要句号 | {"subject-full-stop": ["2", "never"]} |
rules.body-max-line-length | 限制提交消息主体部分(body)每一行的最大字符数 | {"body-max-line-length": ["1", "always", 72]} |
rules.footer-leading-blank | 强制提交消息的 footer 部分前面有一空行 | {"footer-leading-blank": ["error", "always"]} |
Conventional Commits
约定式提交规范是一种基于提交信息的轻量级约定。
它提供了一组简单规则来创建清晰的提交历史,这更有利于编写自动化工具。
提交说明的结构
arduino
<type>[optional scope]: <description> // <类型>[可选 范围]: <描述>
[optional body] // [可选 正文]
[optional footer(s)] // [可选 脚注]
常用类型
type | 说明 |
---|---|
fix: | 表示在代码库中修复了一个bug |
feat: | 表示在代码库中新增了一个功能 |
build: | 用于修改项目构建系统,例如修改依赖库、外部接口或者升级 Node 版本等 |
chore: | 用于对非业务性代码进行修改,例如修改构建流程或者工具配置等 |
ci: | 用于修改持续集成流程 |
docs: | 用于修改文档,例如修改 README 文件、API 文档等 |
style: | 用于修改代码的样式,例如调整缩进、空格、空行等 |
refactor: | 重构代码以提高内部质量,但不改变外部可见行为 |
perf: | 用于优化性能,例如提升代码的性能、减少内存占用等 |
test: | 用于修改测试用例,例如添加、删除、修改代码的测试用例等 |
revert: | 回滚到以前的提交状态,通常用于撤销最近引入的问题或更改 |
常用提交结构示例
csharp
// 包含了描述并且脚注中有破坏性变更的提交说明
feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
// 包含了 ! 字符以提醒注意破坏性变更的提交说明
feat!: send an email to the customer when a product is shipped
// 包含范围的提交说明
feat(lang): add polish language
Commitizen
Commitizen
是一个开源的命令行工具,旨在帮助前端(以及所有使用 Git 的项目)开发者遵循一种标准化的提交消息格式。这种规范化提交信息的方式对于维护项目的提交历史、自动化生成 CHANGELOG、以及配合持续集成流程等具有重要作用。
安装
js
npm install -g commitizen
配置
js
"scripts": {
"commit": "cz"
}
执行
js
git cz
// or
git commit
执行效果图,默认为英文交互
cz-conventional-changelog
cz-conventional-changelog
是Commitizen
的一个适配器(adapter),它专门为遵循 Conventional Commits 规范而设计。Conventional Commits 是一种社区广泛接受的提交消息格式规范,用于增强提交历史的可读性和自动化生成 CHANGELOG 文件。
配置
json
// package.json
{
"config": {
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog",
"disableScopeLowerCase": false,
"disableSubjectLowerCase": false,
"maxHeaderWidth": 100,
"maxLineWidth": 100,
"defaultType": "",
"defaultScope": "",
"defaultSubject": "",
"defaultBody": "",
"defaultIssues": "",
"types": {
...
"feat": {
"description": "A new feature",
"title": "Features"
},
...
}
}
}
}
}
配置项
说明 | |
---|---|
path | 指定 cz-conventional-changelog 适配器的路径 |
config | 更具体的自定义配置对象 |
config.disableScopeLowerCase | 是否禁用将 scope 自动转为小写的功能,默认情况下是转换为小写。设置为 true 可以保持用户输入的 Scope 原始大小写格式。 |
config.disableSubjectLowerCase | 类似于 disableScopeLowerCase,决定是否禁用提交主题(subject)字段自动转为小写。若设为 true ,提交的主题行首字母可以大写或根据原始输入保持大小写状态。 |
config.maxHeaderWidth | 提交信息中所有行的最大长度,包括主体(body)和 footer 部分。超过此宽度的内容同样会被按照指定的字符数进行折行。 |
config.defaultType | 当用户在交互式提交过程中没有明确选择 commit 类型时,使用的默认类型值,如 "feat" 或 "fix" 等。 |
config.defaultScope | 默认的作用域值,如果在提交时未指定作用域,则使用此默认值。 |
config.defaultSubject | 提供一个默认的提交主题,通常只有在特殊情况下才会用到,比如脚本自动生成提交时。 |
config.defaultBody | 默认的提交主体内容,可以用来填充提交信息的详细描述部分,但大多数情况下开发者需要手动填写这部分内容以确保其准确性。 |
config.defaultIssues | 在提交消息中自动包含特定的 issue 关联前缀(如:Closes #123)。 |
config.types | 定义项目所支持的 commit 类型及其描述。这对于提示用户选择合适的类型非常有用。 |
类型中英文提示示例
名称 | 英文提示说明 | 中文提示说明 |
---|---|---|
feat | Introduces a new feature or enhances an existing one | 添加新的功能或改进现有功能 |
fix | Fixes a bug or resolves a defect in the codebase | 修复一个错误或者缺陷 |
docs | Changes only documentation content without altering code logic or functionality | 只修改了文档内容,不影响代码逻辑或功能 |
style | Changes that do not affect the program's behavior, such as formatting, white-space changes, or indentation | 代码格式、空白字符、缩进等不改变程序行为的变动 |
refactor | Code restructuring without adding features or fixing bugs, but possibly improving internal structure | 代码重构,不新增功能也不修复错误,但可能改进内部结构 |
perf | Improves performance, e.g., optimizing algorithms, reducing memory usage, etc. | 提升性能的改动,比如优化算法、减少内存占用等 |
test | Adds missing tests or modifies existing tests for better coverage or other quality metrics | 添加缺失的测试用例,或者修改现有测试以提高覆盖率或其他质量指标 |
build | Changes related to the build system or external dependencies (like npm packages, compilers, etc.) | 与项目构建系统或外部依赖(如 npm 软件包、编译器等)相关的更改 |
ci | Changes to CI configuration files and scripts | 对 CI 配置文件和脚本的更改 |
chore | Maintenance tasks that don't modify source code or tests | 不修改源码或测试的其他维护性任务 |
revert | Reverts a previous commit | 撤销以前的提交 |
配置后的执行效果图
最佳实践
使用场景
- 代码提交
预期目标
- 提交时进行提交规范校验,校验信息包括:
- 类型:必填、类型在预设的配置中
- 描述:必填
- 提交时进行代码检测
- 代码语法:检查语法是否正确,如果不正确抛出错误
- 代码格式:自动格式化代码格式,使代码格式保持统一
- 通过辅助工具帮助开发同学规范提交信息
- 配置
Commitizen
- 配置
分析
如果要实现上述的预期目标,肯定是要在代码提交前执行。所以要用到Git Hooks
中的钩子。pre-commit
常用于运行代码风格检查、commit-msg
常用于验证提交消息格式是否符合团队规范。
配置pre-commit脚本
bash
// .husky > pre-commit
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"
if [[ "$OS" == "Windows_NT" ]]; then
npx.cmd lint-staged
else
npx lint-staged
fi
json
// package.json
{
"lint-staged": {
"*.{js,jsx,vue,ts,tsx,html,vue,css,sass,less}": "eslint --fix"
}
}
配置commit-msg脚本
bash
// .husky > commit-msg
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"
if [[ "$OS" == "Windows_NT" ]]; then
npx.cmd --no-install commitlint -e $GIT_PARAMS
else
npx --no-install commitlint -e $GIT_PARAMS
fi
脚本相关语法不再过多描述,主要是看
if
中执行的命令。
优势与不足
优势
- 使项目规范化,代码风格保持统一
- 易于后期的代码维护
- 减少新人加入项目后的代码上手难度
不足
在使用Commitizen
辅助提交时,要使用命令行的方式,source tree
和 github desktop
的可视化工具就不太好用了。除此之外,source tree
和 github desktop
校验失败时都会抛出错误,不使用Commitizen
时,使用两者工具是没有问题的。
技术清单
名称 | 版本 | 说明 |
---|---|---|
node | v18.16.0 | - |
husky | ^9.0.7 | - |
commitlint | ^18.6.0 | - |
@commitlint/cli | ^18.6.0 | - |
@commitlint/config-conventional | ^18.6.0 | - |
commitizen | ^4.3.0 | - |
cz-conventional-changelog | ^3.3.0 | - |
eslint | ^8.56.0 | 进行代码校验,本文未展开介绍 |
lint-staged | ^15.2.0 | 进行代码校验,本文未展开介绍 |