基本概念
eslint和prettier
- eslint作用:检查代码质量,比如是否有已定义但未使用的变量,或者使用函数式编程的函数是否产生副作用等
- prettier作用:pretter没有对代码的质量进行检查的能力,其只会对代码风格按照指定的规范进行统一,避免一个项目中出现多种不同的代码风格。比如tab键为多少个空格
- 代码质量出问题意味着程序有潜在 Bug,而风格问题充其量也只是看着不爽
eslint规则设置:
// 配置参数
rules: {
"规则名1": [规则值, 规则配置],
"规则名2": [规则值, 规则配置]
}
规则值(决定了是否开启/关闭)
off
或 0:关闭规则warn
或 1:开启规则,warn 级别的错误 (不会导致程序退出)error
或 2:开启规则,error级别的错误(当被触发的时候,程序会退出)
使用配置文件的第一种方式是通过 .eslintrc.* 和 package.json 文件。ESLint 将==自动==在要检测的文件目录里寻找它们,紧接着是父级目录,一直到文件系统的根目录(除非指定 root: true)
自动修复
- vscode安装 eslint 插件后不用我们手动运行检查
node_modules/.bin/eslint yourfile.js
,如果我们的项目中引入并配置了eslint,我们在写代码的时候vscode的eslint插件会根据我们配置的文件自动帮我们检查代码格式是否正确,省去了要手动命令行检查的麻烦 - 自动修复:
--fix
的作用是自动修复根据我们配置的规则检测出来的格式问题
<!--在 package.json 中配置:可自动修复全部对应后缀名的文件-->
"scripts": {
"lint": "./node_modules/.bin/eslint --ext .js,.vue ./ --fix",
},
其实eslint只能fix
掉部分规范具体看文档的规则前面是否带了一个小扳手,如果带的话证明可以修复
- 也可以配置vscode的
setting.json
文件,达到保存自动修复当前文件(也是读取我们项目根目录的Eslint规则)
// settings.json 中的部分配置
{
"editor.formatOnSave": false, // 每次保存自动格式化
"editor.defaultFormatter": "esbenp.prettier-vscode",
"window.zoomLevel": 0, // 原始缩放比例
"editor.codeActionsOnSave": { // 在保存时用eslint规则进行修复
"source.fixAll.eslint": false
},
"eslint.enable": true, //是否开启vscode的eslint
"eslint.options": { //指定vscode的eslint所处理的文件的后缀
"extensions": [
".js",
".vue",
".ts",
".tsx"
]
}
}
基本配置及相关文件解读(eslint+husky+prettier+lint-staged)
配置 .editorconfig
ditorConfig用于在基本代码库中维持一致的编码风格和设置,例如缩进样式、选项卡宽度、行尾字符以及编码等。这里可以根据具体项目用什么框架开发具体设置
在vscode中搜索安装EditorConfig插件,根目录下新建 .edittorconfig文件写入一些配置代码
// .editorconfig
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120
[*.md]
trim_trailing_whitespace = false
配置 Eslint
- 配合vscode使用可以安装 eslint 插件
- 安装以下EsLint包:(注意要安装在开发环境上,还有就是如果你使用的是脚手架的话,选了Eslint选项,会自带这些包。)
"eslint": "^6.7.2",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-vue": "^6.2.2",
- 在项目的根目录下新建.eslintrc.js 文件
// .eslintrc.js 文件内容
// extends:基础配置(我们这里使用的是腾讯的代码规范,配合`prettier`)
extends: ['@tencent/eslint-config-tencent', 'plugin:vue/essential', 'prettier'],
// rules:可以根据需要定义新的规则,或覆盖extends里面的基础规则配置
"rules": {
"semi": ["error", "never"], // 禁止使用分号
}
让Eslint识别Typescript:
- 安装依赖:
tnpm i typescript
tnpm i -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
// @typescript-eslint/parser 是一个eslint的解析器,该解析器利用TypeScript ESTree允许ESLint整理TypeScript源代码。
@typescript-eslint/eslint-plugin
是eslint识别TypeScript规则的插件 我们把他放入 extends 这个数组里。
// eslintrc.js
module.exports = {
"parser": '@typescript-eslint/parser',
"extends": ['plugin:@typescript-eslint/recommended'],
"plugins": ['@typescript-eslint'],
"env": {
"browser": true,
"es6": true
},
"rules": {
"semi": ["error", "never"], // 禁止使用分号
}
};
配置prettier
基本概念:
- 主要用来统一代码格式
- eslint也会对代码进行一定程度的格式校验,但主要是用来对代码规范的扫描,而prettier则是专门用来对代码进行格式化,两个工具各司其职
- 工作原理:将格式化前的代码和格式化后的代码进行比对,如果发现不一样,prettier就会对其进行标记并按照指定的格式化规范进行修复
配置步骤:
- 根目录下新建配置文件.prettierrc.js
// .prettierrc.js 文件
module.exports = {
"printWidth": 80, //一行的字符数,如果超过会进行换行,默认为80
"tabWidth": 2, //一个tab代表几个空格数,默认为80
"useTabs": false, //是否使用tab进行缩进,默认为false,表示用空格进行缩减
"singleQuote": false, //字符串是否使用单引号,默认为false,使用双引号
"semi": true, //行位是否使用分号,默认为true
"trailingComma": "none", //是否使用尾逗号,有三个可选值"<none|es5|all>"
"bracketSpacing": true, //对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
"parser": "babylon" //代码的解析引擎,默认为babylon,与babel相同。
}
- 安装 Prettier 依赖:
// eslint-config-prettier eslint-plugin-prettier 插件就是为了解决冲突的
tnpm i -D prettier eslint-config-prettier eslint-plugin-prettier
Prettier 和 ESLint 一起使用的时候会有冲突,解决方法:
- 首先我们需要使用 eslint-config-prettier 来关掉 (disable) 所有和 Prettier 冲突的 ESLint 的配置(这部分配置就是上面说的,格式问题的配置,所以关掉不会有问题),方法就是在 .eslintrc 里面将 prettier 设为最后一个 extends
// .eslintrc.js 文件
{
"extends": ["prettier"] // prettier 一定要是最后一个,才能确保覆盖
}
- (可选,推荐) 然后再启用 eslint-plugin-prettier ,将 prettier 的 rules 以插件的形式加入到 ESLint 里面。这里插一句,为什么"可选" ?当你使用 Prettier + ESLint 的时候,其实格式问题两个都有参与,disable ESLint 之后,其实格式的问题已经全部由 prettier 接手了。那我们为什么还要这个 plugin?其实是因为我们期望报错的来源依旧是 ESLint ,使用这个,相当于把 Prettier 推荐的格式问题的配置以 ESLint rules 的方式写入,这样相当于可以统一代码问题的来源
// .eslintrc
{
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error"
}
}
配置 husky + lint-staged 构建代码工作流
- 安装 husky lint-staged 依赖
tnpm i -D husky lint-staged
- 配置 husky/.huskyrc.js
// 单独在根目录新建一个 .huskyrc.js 文件
module.exports = {
hooks: {
'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS',
'pre-commit': 'lint-staged',
},
};
// 或者在 package.json 中添加以下配置
"husky": {
"hooks": {
'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS', // commitlint 的配置
'pre-commit': 'lint-staged'
}
}
- 配置 lint-stage/.lintstagedrc.js
// 单独在根目录新建一个 .lintstagedrc.js 文件
module.exports = {
'*.{js,vue,ts}': 'eslint',
};
// 或者在 package.json 中添加以下配置
"lint-staged": {
"*{.ts,.js}":[
"eslint --ext .tsx,.ts --fix ./src",
"prettier --write",
"git add"
]
}
husky作用:
- 为了确保本地的代码已经通过检查才能push到远程,这样才能从一定程度上确保应用的线上质量
- 在本地进行
git commit
的时候开始进行扫描检查
工作原理:
- 在运行
git commit
时候,自动会先去运行prettier --write
格式化代码,再运行eslint
校验代码是否符合规范。这两步都通过后才会提交代码。如果任何一步失败,则会停止提交
git的hook:
-
git的hook可以理解成当执行如git add、git commit等git操作时的回调,可以查看.git文件下的hooks目录,这里存放的是git相关操作的一些脚本例子。通过git hook就可以在本地进行commit的时候触发代码扫描来确保本地代码的质量
-
使用到
lint-staged
工具来识别被加入到stage区文件,就是每次只对当前修改后的文件进行扫描,即只对git add
加入到stage区的文件进行扫描即可,完成对增量代码进行检查
commitlint.config.js(提交规范)
安装:
tnpm install --save-dev @commitlint/config-conventional @commitlint/cli
配置: 在husky的配置加入CommitlIint配置,v1.0.1版本以后为HUSKY_GIT_PARAMS,v0.14.3为GIT_PARAMS
// package.json文件
"husky": {
"hooks": {
"pre-commit": "npm run test",
"commit-msg": "commitlint -e $HUSKY_GIT_PARAMS" // 关键代码
}
},
提交格式:
<type>: <subject>
常用type类别:
- upd:更新某功能(不是 feat, 不是 fix)
- feat:新功能(feature)
- fix:修补bug
- docs:文档(documentation)
- style: 格式(不影响代码运行的变动)
- refactor:重构(即不是新增功能,也不是修改bug的代码变动)
- test:增加测试
- chore:构建过程或辅助工具的变动
例子:
git commit -m 'feat: 增加 xxx 功能'
git commit -m 'bug: 修复 xxx 功能'
commitlint.config.js文件配置:
- rule配置说明::rule由name和配置数组组成,如:'name:[0, 'always', 72]',数组中第一位为level,可选0,1,2,0为disable,1为warning,2为error,第二位为应用与否,可选always|never,第三位该rule的值。具体配置例子如下
// 配置文件commitlint.config.js,当然也可以是 .commitlintrc.js
module.exports = {
extends: [
"@commitlint/config-conventional"
],
rules: {
'type-enum': [2, 'always', [
'upd', 'feat', 'fix', 'refactor', 'docs', 'chore', 'style', 'revert'
]],
'type-case': [0],
'type-empty': [0],
'scope-empty': [0],
'scope-case': [0],
'subject-full-stop': [0, 'never'],
'subject-case': [0, 'never'],
'header-max-length': [0, 'always', 72]
}
};
.ls-lint.yml(文件命名规范)
- PascalCase
- kebab-case
执行流程
- 待提交的代码git add 添加到暂存区;
- 执行 git commit;
- husky注册在git pre-commit的钩子函数被调用,执行lint-staged;
- lint-staged 取得所有被提交的文件依次执行写好的任务(ESLint 和 Prettier);
- 如果有错误(没通过ESlint检查)则停止任务,同时打印错误信息,等待修复后再次执行commit;
- 成功commit,可push到远程
在上述流程中,有这样几个核心点:
- husky注册git的钩子函数保证在git 执行commit时调用代码扫描的动作;
- eslint完成按照配置的规则进行扫描;
- Lint-staged保证只对当前add到git stage区的文件进行扫描操作,这样做的原因在于,如果对全工程的文件进行扫描的话,并且之前的前端工程并未注重代码规则的检测的话,很大可能性会出现成百上千的error,基本上心里是崩溃的。因此,只对当前add的文件进行检测,达到及时止损的目的,历史代码可以切到新的分支进行修复后再进行合并
总结:
- 通过Eslint去约束Javascript/Typescript
- Prettier 美化代码,统一代码风格
- 使用 husky + lint-staged 在commit前做检查,避免存在不规范或者存在bug的代码入仓库
使用以上工具,就可以保证我们从本地开发到commit提交代码都是经过校验的!因此我们在平时开发写代码的时候会实时校验,然后在用gitcommit提交代码的时候也会再校验一次,这样就有了双重保障代码的质量!!!
参考文章
《从零配置 Eslint + Prettier + husky + lint-staged 构建前端代码工作流》、《eslint+husky+prettier+lint-staged提升前端应用质量》