制定前端代码提交规范,能更方便的维护我们的项目代码,尤其是多人开发时格外重要。下面介绍下使用 commitlint+eslint+prettier 规范化代码提交。
插件简介
项目中用到的插件包括:husky, lint-staged, eslint, prettier, commitlint。
1. husky
在 git 中,每次执行 git commit, git push 等操作时,会触发一个或多个 shell 脚本,这些脚本称为钩子,存放在 .git/hooks 目录下。钩子分为前置钩子和后置钩子,前置钩子为 git 命令调用前执行,后置钩子为 git 命令完成后执行。
所以在 git 命令提交时,我们可以额外做一些事情,比如提交前的代码检测,提交后的部署等功能。husky 插件可以在 git 执行特定事件时触发运行特定脚本,支持 git 所有的钩子。这里利用 husky 插件来实现代码提交前的代码格式化,代码检测,commit 信息校验等功能。
4.x以上
包安装:
cnpm i husky --save-dev
packages.json 添加配置:
"scripts": {
"prepare": "husky install" // 包安装完成后,激活生成钩子脚本,包安装后自动执行
},
npm run prepare
添加自定义钩子:
npx husky add .husky/pre-commit "npx lint-staged"
npx husky add .husky/commit-msg "npx --no -- commitlint --edit ${1}\"
添加完成后,根目录下会生成 .husky 文件夹,将钩子文件推到远端仓库。以后每次代码推送,都会执行钩子文件中定义的命令。
2. lint-staged
lint-staged 插件代表只处理 git 暂存区的文件,这样仅会修改到自己提交的文件,不会影响项目其他未提交的文件,控制代码修改风险,同时也提高处理性能。
包安装:
cnpm i lint-staged --save-dev
packages.json 添加配置:
"lint-staged": {
"*.{js,jsx,ts,tsx,vue,md,html,css}": [
"eslint --fix --quiet"
]
}
或者在根目录下新建 .lintstagedrc 文件,添加配置:
{
"*.{js,jsx,ts,tsx,vue}": [
"eslint --fix --quiet"
]
}
通过 husky 钩子执行 lint-staged。
npx husky add .husky/pre-commit "npx lint-staged"
3. eslint
ESLint 是一款插件化的 JavaScript 代码静态检查工具,其核心是通过对代码解析得到的 AST(Abstract Syntax Tree,抽象语法树)进行模式匹配,来分析代码达到检查代码质量和风格问题的能力。
包安装:
cnpm i eslint eslint-config-airbnb-base eslint-config-prettier eslint-plugin-import eslint-plugin-prettier eslint-plugin-vue @typescript-eslint/eslint-plugin @typescript-eslint/parser --save-dev
根目录下新增 .eslintrc.js 文件:
// .eslintrc.js
module.exports = {
root: true,
env: {
browser: true,
es6: true,
node: true,
'vue/setup-compiler-macros': true,
},
globals: {
wx: false,
AMap: true,
AMapUI: true,
},
extends: [
'airbnb-base',
'plugin:vue/essential',
'plugin:prettier/recommended',
],
parserOptions: {
ecmaVersion: 12,
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
plugins: ['vue', '@typescript-eslint'],
settings: {},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', // 禁止console
'no-unused-expressions': [
'error',
{
allowShortCircuit: true, // 允许短路逻辑
allowTernary: true, // 允许三目运算
},
],
'import/prefer-default-export': 'off', // 如果只有一个值,要用 default 导出
'import/no-unresolved': 'off', // import识别路径,因为alias设置
'import/extensions': 'off', // 扩展简写
'no-param-reassign': 'off', // 函数参数修改
'no-plusplus': 'off', // 一元操作符
'no-nested-ternary': 'off', // 禁用嵌套的三元表达式
'no-bitwise': 'off', // 禁用按位运算符
'no-multi-assign': 'off', // 禁止连续赋值
'no-unsafe-optional-chaining': 'warn', // 不安全的可选链
'no-restricted-globals': 'off', // 指定不希望在应用程序中使用的全局变量名称
'no-underscore-dangle': 'off', // 不允许在标识符中使用悬空下划线
'no-use-before-define': 'warn', // 在遇到对尚未声明的标识符的引用时发出警告
'no-empty': ['error', { allowEmptyCatch: true }], // 不允许空块语句, allowEmptyCatch: true允许空catch子句
'consistent-return': 'off', // return语句总是或永远不指定值
'no-case-declarations': 'off', // 防止访问未初始化的词汇绑定以及跨越事例子句访问提升
'no-async-promise-executor': 'off', // promise是否是异步函数
'default-param-last': 'warn', // 带默认值的参数放最后面
'prefer-destructuring': ['error', { object: true, array: false }], // 是否优先使用数组和对象解构
eqeqeq: 'warn', // 消除类型不安全的等式操作符
'vue/no-v-model-argument': 'off', // v-model 带参数
'vue/no-multiple-template-root': 'off', // 根元素只有一个
'vue/multi-word-component-names': 'off', // 组件名称是否是多字母
'vue/no-mutating-props': 'warn',
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
},
}
根目录下新增 .eslintignore 文件:( eslint 校验忽略目录)
.DS_Store
.history
.husky
dist
node_modules
*.local
yarn-error.log
yarn.lock
tests
types
types.ts
代码执行 eslint :
eslint --fix --quiet . --ext .js,.ts,.vue
eslint 核心配置项解析:
- parser 解析器:ESLint 默认使用 Espreer 作为其解析器,但是该解析器仅支持最新的 ECMPScript(es5) 标准,对于实验性的语法和非标准(例如 Flow 或 TypeScript 类型)语法是不支持的。因此,开源社区提供了两种解析器:babel-eslint 和 @typescript-eslint/parser。
- parserOptions 解析器选项
- env 和 global 环境和全局变量:代码中未声明的变量可能是库中定义的,需要在此设置中声明。值有三个:writable 可重写,readonly 只读和 off 禁用。
- rules 规则:www.verydoc.net/eslint/0000…
- plugins 插件:自定义插件来检查代码语法。比如 ts 开发需要将解析器修改为 @typescript-eslint/parser,同时安装 @typescript-eslint/eslint-plugin 插件来拓展规则。
- extends扩展:继承已有的配置文件,值为字符串或数组。
4. prettier
prettier 是一个纯粹的代码格式化工具。eslint 主要做代码检查,代码格式化有限,所以与 prettier 搭配使用。用 eslint 进行代码校验,用 prettier 统一代码风格。
包安装:
cnpm i prettier --save-dev
根目录下新增 .prettierrc.js 文件:
// .prettierrc.js
module.exports = {
// extends: ["airbnb", "prettier"],
// 一行最多 80 字符
printWidth: 80,
// 使用 2 个空格缩进
tabWidth: 2,
// 是否使用tab进行缩进
useTabs: true,
// 行尾不需要有分号
semi: false,
// 使用单引号
singleQuote: true,
// 对象的 key 仅在必要时用引号
quoteProps: 'as-needed',
// jsx 不使用单引号,而使用双引号
jsxSingleQuote: false,
// 是否使用尾逗号,有三个可选值"<none|es5|all>"
trailingComma: 'es5',
// 大括号内的首尾需要空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 箭头函数,如果只有一个参数则省略括号
arrowParens: 'avoid',
// 使用默认的折行标准
proseWrap: 'preserve',
// 标签折行
htmlWhitespaceSensitivity: 'ignore',
// 换行符使用 lf
endOfLine: 'lf',
// 文件后缀名对应的格式化处理器
// parsers: {
// ".jsx": "flow",
// ".scss": "scss",
// ".less": "css",
// ".vue": "vue",
// ".ux": "vue",
// ".yml": "yaml",
// ".foo": "flow",
// },
}
根目录下新增 .prettierignore 文件:(格式化忽略的目录)
.DS_Store
.history
.husky
dist
node_modules
*.local
yarn-error.log
yarn.lock
代码执行 prettier 命令:
prettier --write .
prettier 与 eslint 配合使用
安装包:
- eslint-config-prettier 的作用是关掉和 prettier 冲突的 eslint 配置。
- eslint-plugin-prettier 的作用时是将 prettier 的能力集成到 eslint 中。
cnpm i eslint-config-prettier eslint-plugin-prettier --save-dev
.eslintrc.js 文件配置:
{
"extends": [
"plugin:prettier/recommended" // 放最后面,避免被覆盖
]
}
5. commitlint
commitlint 是一个命令行工具,对 git commit 的信息做验证。
安装包:
cnpm i @commitlint/cli @commitlint/config-conventional
根目录下新建 commitlint.config.js 文件:
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'], // 继承官方提供的规则
}
husky 添加钩子使用 commitlint:
npx husky add .husky/commit-msg \"npx --no -- commitlint --edit ${1}\"
npx --no :表示只使用本地项目 node_modules 的脚本,找不到的时候不会自动下载。
commitlint --edit <文件名>:执行 commitlint 命令行工具,并使用 --edit 选项,从一个文件里提取 commit 内容进行校验。校验规则由 commitlint.config.js 配置文件来指定。在 commit-msg 脚本中,通过
$1
拿到提交信息。$1
指向的是.git/COMMIT_EDITMSG
文件,该文件保存着最后一次提交的 commit 信息。
vscode 插件支持
vscode 开发时,安装对应插件,可以实现代码保存的时候自动提示或修复。
1. 插件安装
vscode 扩展里安装 eslint 插件, prettier 插件,EditorConfig for VS Code 插件。
EditorConfig for VS Code 插件可以让编译器读取配置文件,并且按照配置文件 .editorconfig 里面的规定来格式化代码。
2. 设置修改
VSCode 的 setting.json 设置分为用户区和工作区两个级别,其中用户区会对所有项目生效,而工作区只对当前项目生效。
用户区
修改设置项有以下两种方式:
方式一:
打开的 settings.json 文件添加如下代码:
"editor.formatOnSave": true, // 保存的时候格式化
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
方式二:
通过 vscode 设置界面来操作。
工作区
根目录下创建 .vscode/settings.json 文件, 并添加如下代码:
{
"editor.formatOnSave": true, // 保存的时候格式化
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
}
}
一般建议使用用户区级别的设置,针对所有项目生效,统一配置。
3. .editorconfig 设置
根目录下新增 .editorconfig 文件,定义编辑器的代码规范规则,该规则高于编译器默认的代码规范规则。该配置项提供给 EditorConfig for VS Code 插件使用。
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 2
项目实践
1. 安装包
cnpm i @commitlint/cli @commitlint/config-conventional @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-airbnb-base eslint-config-prettier eslint-plugin-import eslint-plugin-prettier eslint-plugin-vue husky lint-staged prettier --save-dev
2. 修改 packages.json
增加 lint-staged 设置项:
{
...
"scripts": {
"prepare": "husky install",
"huskyInit": "npx husky add .husky/pre-commit \"npx lint-staged --allow-empty\" && npx husky add .husky/commit-msg \"npx --no -- commitlint --edit ${1}\"",
"prettier": "prettier --write .",
"lint": "eslint --fix --quiet . --ext .js,.ts,.vue"
},
"devDependencies": {
"@commitlint/cli": "^17.4.2",
"@commitlint/config-conventional": "^17.4.2",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"eslint": "^8.14.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.7.1",
"husky": "^7.0.4",
"lint-staged": "^13.1.0",
"prettier": "^2.6.2",
...
},
"lint-staged": {
"*.{js,jsx,ts,tsx,vue,md,html,css}": [
"eslint --fix --quiet"
]
}
}
执行以下命令初始化 husky,并生成钩子文件:
npm run prepare
npm run huskyInit
3. 添加配置文件
- .editorconfig
- .eslintrc.js
- .eslintignore
- .prettierignore
- .prettierrc.js
- commitlint.config.js
4. 总结
当git commit的时候,执行钩子逻辑,pre-commit 钩子对暂存区的文件执行 eslint 校验,以及 prettier 格式化;当校验通过,且代码格式化完成后执行 commit-msg 钩子逻辑,对 git commit 的提交信息做格式验证,验证通过后 commit 成功。