husky+lint-staged+commitlint规范代码提交
# 写在前面
个人开发和团队开发最大的不同,是团队协作时,因为编码风格和代码提交风格不统一,导致沟通上的代价很高。
举个例子,程序员最头疼的是 A 和 B 分别使用 2 个空格和 4 个空格进行缩进,如果他们维护同一份文件,即使文件不做任何代码改动,但格式化之后 git 也会显示大量的空格改动。如果加上本身的代码修改,那么查看代码差异将是一件痛苦的事,加之为了方便查看提交记录,因此有必要统一团队的编码和提交代码规范。
关于代码质量的规范,已经在Eslint 使用一文进行了探讨,本文将讨论利用流行的代码提交工具,包括husky
和commitlint
。
本机环境如下:
node -v
v14.17.5
npm -v
6.14.14
git --version
git version 2.33.0.windows.1
2
3
4
5
6
# 手动 lint
npm i eslint -D
npx eslint --init
√ How would you like to use ESLint? · style
√ What type of modules does your project use? · esm
√ Which framework does your project use? · none
√ Does your project use TypeScript? · No / Yes
√ Where does your code run? · browser
√ How would you like to define a style for your project? · guide
√ Which style guide do you want to follow? · airbnb
√ What format do you want your config file to be in? · JavaScript
2
3
4
5
6
7
8
9
10
这里选择了airbnb
的规范,修改package.json
{
"scripts": {
"lint": "eslint --ext .js src/"
}
}
2
3
4
5
新增文件
// src/index.js
const a = 1
function b(name) {
console.log(name)
}
console.log(a)
2
3
4
5
6
7
8
开始 lint
npm run lint
发现控制台报错信息
src\index.js
1:12 error Missing semicolon semi
3:10 error 'b' is defined but never used no-unused-vars
4:1 error Expected indentation of 2 spaces but found 4 indent
4:5 warning Unexpected console statement no-console
4:22 error Missing semicolon semi
7:1 warning Unexpected console statement no-console
7:15 error Newline required at end of file but not found eol-last
7:15 error Missing semicolon
2
3
4
5
6
7
8
9
# husky
husky (opens new window)是 git hooks 的管理工具,通常使用频率较高的钩子是:
- pre-commit 提交之前运行,通常用来检查代码质量,统一代码格式。可以使用 git commit --no-verify 来忽略。
- commit-msg 在输入提交信息之后调用,通常可以用来提醒开发者提交信息是否符合团队规范。
以这 2 个钩子为例,我们使用husky
来进行代码提交的管理。
由于 husky 升级到 6.x 后,出现破坏式更新,之前的配置方式已失效,见husky 使用总结 (opens new window)。参考官网的方式进行安装和配置,如下:
# 安装
npm install husky --save-dev
# 编辑 package.json
{
"scripts": {
"prepare": "husky install"
}
}
2
3
4
5
然后执行npm run prepare
,发现根目录下生成了.husky
目录。
# 创建 hook
npx husky add .husky/pre-commit
然后就生成了 pre-commit 文件,内容如下:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
undefined
2
3
4
将undefined
改为echo pre-commit && npm run lint
尝试提交代码
git commit -m 'save'
钩子触发了,如果有代码不符合 eslint 规范,那么提交将被中断。
同理创建commit-msg
钩子
npx husky add .husky/commit-msg
现在 husky 的基本使用就完成了,接下来我们利用这 2 个钩子来进行代码质量和提交规范的管理。
# lint-staged
lint-staged (opens new window)只检测暂存区的代码,一般配合husky
一起使用。
npm install lint-staged -D
根目录下新建.lintstagedrc.js
,设置如下
module.exports = {
'*.{js,jsx,ts,tsx,vue}': 'eslint --fix',
}
2
3
然后修改.husky/pre-commit
为
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
2
3
4
就生效了,它的操作模式是:当暂存区有文件 commit 时,触发pre-commit
钩子,执行lint-staged
命令,根据.lintstagedrcl.js
配置,执行eslint --fix file.ext
。
注意,这种模式下,只会检测和操作暂存区的代码,即使之前的旧代码有不符合规范,也不会被检测和修改到。
eslint 只会校验 js 代码的质量,对于其它文件的风格,一般使用prettier
来统一风格。因此这里也加上。
npm i prettier -D
然后修改.lintstagedrc.js
module.exports = {
// ...
'*.{js,jsx,ts,tsx,md,html,css}': 'prettier --write',
}
2
3
4
此时可以加个readme.md
文件来测试看看。
注意:上述行为都默认没有安装 vscode 的相关插件,事实上 eslint,prettier 等插件会在实时编码过程中非常有用,许多风格可以在保存代码时就统一了。本文所说的在提交时进行风格统一,是提交代码前的最后一层保障。
# commitlint
1.基本介绍
commitlint (opens new window)的基本格式如下:
<type>[optional scope]: <description>
[optional body]
[optional footer]
2
3
4
5
type
基于angular 规范 (opens new window),默认有如下几种,可以自定义修改。
build // 涉及到工程构建或者依赖变动
ci // CI(持续集成)配置文件或脚本有变动
chore // 不好定义的其他修改如文档,代码生成等
docs // 文档
feat // 新特性
fix // 修复bug
perf // 优化
refactor // 重构(非新增特性,非bug修复)
revert // 回退
style // 不影响代码的格式化等
test // 测试用例补充或修改
2
3
4
5
6
7
8
9
10
11
scope
用括号括起来,说明提交影响的范围。
description
是本次提交的简短描述,一般不超过 50 个字符。
body
是提交的详细描述。
footer
一般是破坏性改动或者关闭 issue 时才使用。
2.使用
# 安装
npm install --save-dev @commitlint/config-conventional @commitlint/cli
# 新增配置文件
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
# 设置hook
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
2
3
4
5
6
7
8
此时提交时,就必须遵循 commitlint 的规则了。
这里有个小坑,提交时控制台报错
commitlint.config.js:1
SyntaxError: Invalid or unexpected token
...
2
3
将文件格式设置为 UTF-8 即可。
# 参考资料
# 附录
本次测试,最终的 package.json 如下:
{
"name": "test-husky",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint --ext .js src/",
"prepare": "husky install"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@commitlint/cli": "^13.1.0",
"@commitlint/config-conventional": "^13.1.0",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-plugin-import": "^2.24.2",
"husky": "^7.0.2",
"lint-staged": "^11.1.2",
"prettier": "^2.4.1"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24