前言
前端工程化中,约束规范是很重要的一个环节,不能十个工程师,十种代码风格,这无疑会增加团队对代码的维护负担以及心理压力,特别碰到强迫症的同学,一看跟我风格不一样,直接全部改掉,剩下其他同学在风中凌乱。
大纲
本文涉及到的约束规范主要包括:
- ESLint
- IDE
- Git Hooks
- 总结
- package.json 文件
ESLint
ESLint 大家都不陌生,它可以查找并修复 JavaScript 代码中的问题
特点一:发现问题
ESLint 静态分析你的代码以发现问题。
特点二:自动修复
ESLint 发现的许多问题都可以自动修复。ESLint 修复是语法感知的,因此你不会遇到传统查找和替换算法引入的错误。
特点三:定制
预处理代码,使用自定义解析器,并编写与 ESLint 的内置规则一起工作的自己的规则。你可以自定义 ESLint 以完全按照你的项目需要的方式工作。
如何配置
npm install eslint --save-dev
规则需要统一集中配置,ESLint 会默认读取配置文件 .eslintrc 来解析,而规则集在 rules 中进行配置
{
"rules": {
// 函数括号前面不加空格
'space-before-function-paren': ['error', 'never'],
// 关闭要求 require() 出现在顶层模块作用域中
'global-require': 0,
// 关闭关闭类方法中必须使用this
'class-methods-use-this': 0,
}
}
rules 的配置参考文档和最佳实践可以参考下文:eslint-rules
那 eslint 有这么多规则,我们需要一个一个去研究然后一个一个去配置吗?
当然不用啦,github 上已经有大神总结了一套优雅的规则
part one —— ctrl C + ctrl V
官方提供的简单且实用的配置:eslint-recommended
part two —— extends
优秀团队 airbnb(爱彼迎)设定了一套约束特别强的规范:airbnb/javascript
当配置 .eslintrc 时,使用 config.extends 将会继承已有的 .eslintrc 配置文件,配置时可省略 eslint-config- 前缀
比如使用 airbnb-base,我们将基于 eslint-config-airbnb-base 这份 eslint 配置文件,再补充自己的配置文件
{
"extends": ["airbnb-base"],
"rules": {
// 函数括号前面不加空格
'space-before-function-paren': ['error', 'never'],
// 关闭要求 require() 出现在顶层模块作用域中
'global-require': 0,
// 关闭关闭类方法中必须使用this
'class-methods-use-this': 0,
}
}
vue 项目可以用以下规则: npm install --save-dev eslint-config-vue
{
"extends": "vue"
}
假如是 umi 项目,也可以使用包含 prettier,eslint,stylelint 的配置文件合集 umi-fabric
npm i @umijs/fabric --save-dev
{
"extends": [require.resolve('@umijs/fabric/dist/eslint')]
}
IDE
编辑器以 vscode 为例
我们需要安装一个插件:eslint
打开配置
切换到 JSON 配置信息
相关配置信息可以参考如下链接:microsoft-vscode-eslint
推荐先开启下面两个配置:
{
"eslint.format.enable": true, // 用例格式化代码
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true // 保存代码时自动修复
},
}
Git Hooks
有同学看到这就要说了,这也太复杂了,我不想搞呀,能不能简单点,敲代码的方式简单点,我直接提交代码了,不整这些花里胡哨的。
但是很快他就傻眼了,他提交不了呀,被拦截了。
拦截他的大哥有:
pre-commit
这是 git 在你键入提交信息前运行的钩子。它用于检查即将提交的快照,例如,检查是否有所遗漏,确保测试运行,以及核查代码。
在项目目录下,我们可以看到 git 所有的 hook
有这位大哥还不行,太单薄了,还得有左青龙护法 —— husky
husky(不是狗狗哈士奇🐶)
当你提交或推送时,你可以使用它来 lint 提交消息、运行测试、lint 代码等(所有的hooks)
// 提示:在我们前面已经把 eslint 配置好的前提下,执行如下操作
// 下载 husky 4.x 版本
npm install husky@4.2.5 --save-dev
// 配置 package.json
// 添加 scripts
"scripts": {
"lint": "eslint . --cache"
},
// 添加 husky 配置
"husky": {
"hooks": {
"pre-commit": "npm run lint"
}
},
现在创建一个 demo.js 并写上如下内容
// TODO
const a = 3
如果你前面 eslint 设置成功的话,将看到如下提示
此时执行 git commit -m 'test' 提交代码会发现提交失败,并且有如下提示:
说明我们通过 pre-commit 钩子在提交代码前做 eslint 校验成功了 🎉🎉🎉
但是这样存在一个问题,假如我们通过某种方式绕过了 git hooks 的校验(后面会讲到)讲有错误的代码提交上去了,我们下次再做上述操作时,eslint 会扫描所有代码,速度会比较慢
这个时候就得请出我们的右白虎护法 —— lint-staged
lint-staged
该项目包含一个脚本,该脚本将运行任意 shell 任务,并将暂存文件列表作为参数,由指定的 glob 模式过滤。
npm i lint-staged --save-dev
类似如下配置:
"scripts": {
"lint": "eslint . --cache", // 删除,可以不用了
"lint-staged:js": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx "
},
"husky": {
"hooks": {
"pre-commit": "lint-staged" // git hook 改成执行 lint-staged
}
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js"
}
我们再次提交代码试一下,可以看到,现在只提示了在暂存区代码的错误
更优雅
commit-msg 检查 —— commitlint
检查 git commit -m 'xxx' 的 message 是否符合规范
// 安装 @commitlint/cli @commitlint/config-conventional
npm install @commitlint/cli @commitlint/config-conventional -D
// 采用基于 vue-cli3 的代码提交检查规范 vue-cli-plugin-commitlint
npm install vue-cli-plugin-commitlint -D
可以在 .commitlintrc.js 中定义配置
module.exports = {
extends: ['./node_modules/vue-cli-plugin-commitlint/lib/lint'],
}
配合 husky 使用
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -e $HUSKY_GIT_PARAMS"
}
}
测试一下 git commit -m 'test' 会发现报如下错误
正确姿势如下(具体规范,可参考:what-is-commitlint)
更更优雅一点
优雅生成 message —— commitizen
当使用 Commitizen 提交时,系统会提示你在提交时填写所有必需的提交字段。比如上面使用 commitlint 时,提交完之后才提示需要加对应的规范钩子。
使用 Commitizen无需再等待 git commit 钩子运行并拒绝你的提交。不再需要通过 CONTRIBUTING.md 来查找首选格式。 获取有关提交消息格式的即时反馈,并提示输入必填字段。
npm install -g commitizen
// package.json
"scripts": {
"cz": "git add . && git cz"
}
"config": {
"commitizen": {
"path": "./node_modules/vue-cli-plugin-commitlint/lib/cz"
}
}
安装成功后,Commitizen 会生成 git cz 命令,用来替代 git commit
执行 npm run cz 出现如下提示
要解决此错误,我们再需要安装一个 right-pad
npm install right-pad -D
好了,再次执行 npm run cz,就会出现非常友好的 message 了
更更更优雅一点
优雅生成 change log —— 提交版本记录
npm install conventional-changelog-cli -D
// package.json
"scripts": {
"cz": "npm run log && git add . && git cz"
}
再次执行 npm run cz,就会生成一个 CHANGELOG.md 文件随着本次代码提交一起提交上去
// CHANGELOG.md
# 1.0.0 (2021-12-05)
### 🌟 新功能
范围|描述|commitId
--|--|--
- | test | [4ffaad2](https://gitee.com/HY0606/git-hook-demo/commits/4ffaad2)
范围|描述|commitId
--|--|--
- | test | [05ef22a](https://gitee.com/HY0606/git-hook-demo/commits/05ef22a)
- | test | [0191aec](https://gitee.com/HY0606/git-hook-demo/commits/0191aec)
- | Initial commit | [56ff86a](https://gitee.com/HY0606/git-hook-demo/commits/56ff86a)
vscode 可以下载 Markdown Preview Enhanced 插件,查看 md 文件预览模式
总结
至此,一套提交代码规范,并且生成 CHANGELOG 的配置就算完成了,这样可以极大的帮助我们统一代码规范,减少多人协作的沟通的成本,让大家都能早点下班 🐶
希望对大家有所帮助,如果哪里写错了,请大家多多指出。
package.json
// package.json
{
"name": "git-hook-demo",
"version": "1.0.0",
"description": "#### Description 实验 husky 管理 git hook",
"main": "demo.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"lint-staged:js": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx ",
"commit": "git cz",
"log": "conventional-changelog --config ./node_modules/vue-cli-plugin-commitlint/lib/log -i CHANGELOG.md -s -r 0",
"cz": "npm run log && git add . && git cz"
},
"repository": {
"type": "git",
"url": "https://gitee.com/HY0606/git-hook-demo.git"
},
"author": "",
"license": "ISC",
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -e $HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js"
},
"dependencies": {
"eslint": "^8.3.0",
"husky": "^4.2.5"
},
"devDependencies": {
"@commitlint/cli": "^15.0.0",
"@commitlint/config-conventional": "^15.0.0",
"commitizen": "^4.2.4",
"conventional-changelog-cli": "^2.1.1",
"lint-staged": "^12.1.2",
"right-pad": "^1.0.1",
"vue-cli-plugin-commitlint": "^1.0.12"
},
"config": {
"commitizen": {
"path": "./node_modules/vue-cli-plugin-commitlint/lib/cz"
}
}
}