本文主要涉及如下几个方面:
- 如何让Prettier和Eslint两个校验工具协同合作,对代码进行校验和格式化。
- 如何配置Vscode,利用Prettier和Eslint的规则实现保存时自动格式化。
- 如何利用Husky和lint-staged,实现Git commit提交之前,对Git暂存区代码实现校验和格式化。
1、 Why Both Prettier & Eslint
Prettier和Eslint两者都能校验且修改代码格式,为什么同时需要这两个工具?
- 两者关注点侧重不一样,
Prettier
只关注代码格式,Eslint
侧重语法检查,同时带有格式检查。 Prettier
不针对具体语言,且开箱即用。eslint 针对特别的语言需要特别的配置。
在前端项目中,js、ts、tsx
等可以使用 eslint
校验和格式化,其他如 html
和 css
等可以交给开箱即用的 Prettier
来处理
2、 Eslint 安装配置
如果是在已有 eslint
配置的项目基础上改造,可以跳过这一小节
- 执行
npm install eslint --save-dev
- 项目根目录下创建
.eslintrc
和.eslintignore
,并根据项目需要配置。你也可以根据自己的喜好选择配置文件的格式。本文主要关注点在 eslint 和 prettier 的协作上,所以关于 eslint 的详细配置还请参考其文档。你完全可以在已经配置有 eslint 的项目基础上继续下面的实操试验。 - 在
packages.json
的 script 中添加如下两条命令:
{
"lint": "eslint",
"lint:fix": "eslint --fix"
}
3、 安装配置 prettier
- 执行
npm install prettier --save-dev
- 在根目录下新建.prettierrc文件,该文件是Prettier规则的配置文件,每一条对应一个规则,举例如下:
{
"semi": false,
"singleQuote": true
// 其他规则
}
同样该文件也支持多种格式,可根据自己的喜好选择。
添加该文件后, vscode setting.json 配置中,以prettier.
开头的私人规则将不会生效。后续在工具自动格式化代码时,如果发现与预期不符,可以来这里修改相关规则。
如果想忽略某些文件检查,可以在根目录下添加.prettierignore配置文件,写入希望忽略的文件路径。
- 添加命令
在
packages.json
的scripts中添加如下两条命令:
{
"prettier": "prettier src --check",
"prettier:fix": "prettier src --write"
}
prettier
命令用于检查src文件夹下所有文件的格式,prettier:fix
则格式化src文件夹下所有文件的格式。
到目前为止,我们有eslint和prettier两种处理代码格式的工具,但两者各自为政,没有很好的协同合作,甚至在有些地方两者的规则还有可能冲突,所以还需要进一步配置让两者协同起来。
4、 eslint和prettier协同
- 安装
eslint-plugin-prettier
npm install eslint-plugin-prettier --save-dev
eslint-plugin-prettier
是一个eslint插件,它能将Prettier作为eslint的插件调用
- eslint配置
在 eslintrc 的 plugins 配置中加入 prettier 插件:
{
"plugins": ["prettier"]
}
5、 处理冲突
两个工具都有代码格式校验的规则,相互之间有冲突,可使用eslint-config-prettier
来处理,该eslint扩展关掉了和prettier相冲突的eslint规则,保证一致性。
- 安装:
npm install eslint-config-prettier -D
- eslintrc 配置如下,注意 prettier 配置的位置:
{
// ❗prettier一定要放在extends列表的最后
"extends": ["xxx", "prettier"],
"plugins": ["prettier"]
}
6、 vscode 配置
- 插件及配置
vscode 插件搜索eslint
和esbenp.prettier-vscode
并安装
eslint
插件可以对错误高亮显示
esbenp.prettier-vscode
插件则用来格式化文件
修改 setting.json 配置:
{
"editor.formatOnSave": true, // 保存自动修正
"editor.defaultFormatter": "esbenp.prettier-vscode", // 全局配置。prettier格式化代码的vscode插件
"editor.codeActionsOnSave": {
"source.organizeImports": true, // 开启import排序
"source.fixAll.eslint": true // 保存自动执行eslint --fix
},
"[typescript, typescriptreact, javascript]": {
// 禁用prettier格式化,将这些类型文件的格式化交给eslint。覆盖全局配置
"editor.defaultFormatter": null,
"editor.formatOnSave": false
}
}
editor.formatOnSave
和editor.defaultFormatter
规则打开了保存时格式化文档功能,并且指定默认的格式化工具为esbenp.prettier-vscode
。
editor.codeActionsOnSave
规则打开了保存时执行eslint的自动fix功能。同时对[typescript, typescriptreact, javascript]
这些类型的文件关掉了prettier的自动修复功能,也就是覆盖了前面的全局配置。
为什么要这么做?为什么不直接用prettier的自动格式化修复所有的文件?因为eslint除了检查格式以外,还有语法检查的工作,可以修复部分语法问题。同时prettier是作为eslint的一个插件运行的,prettier的校验问题也可以利用eslint的fix得以修复。
那为什么还要在全局设置prettier的自动格式化,直接用eslint不就行了?对于[typescript, typescriptreact, javascript]
这些类型文件,我们确实这么做了,但是还有其他类型的文件也需要格式化,比如css和html文件,eslint可能没有安装相应的规则,那就利用prettier来做一个保底。
此时,你已经可以在编辑器保存是调用eslint的fix功能,或者prettier的格式化功能,自动格式化编辑的文档了。
但是,eslint和prettier的配置可以在团队共享,编辑器的配置却是很私人的东西,无法保证所有的人都一致。假如有人关掉了编辑器自动修复功能,或者配置有误,那又怎么保证提交的代码质量呢?
7、 pre-commit校验
Git提供了很多的钩子,供使用者自行编写逻辑,在特定的命令执行阶段执行。那么对于代码质量检查,可以在commit之前检查代码是否符合要求,如果不合格,则拒绝执行commit。但是git脚本的编写还是很有挑战的,同时,这些钩子的脚本还是在私人机器上,无法共享,即便共享在项目中,也还需要额外的命令才能生效。好在我们有husky,它的作用就是让git的用起来更加方便。
husky
- 安装
npm install husky -D
- packages.json的scripts中添加
"prepare": "husky install"
- 执行
npm run prepare
。此时,你的项目根目录会多出一个.husky
文件夹 - 在
.husky
文件夹下添加pre-commit
文件,写入如下内容:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# lint是在配置eslint时,添加在packages.json中的命令
# 你也可以替换成你想执行的任何命令
npm run lint
此时,在执行git commit
命令之前,会先执行npm run lint
,如果代码检查未通过,commit命令将被中断,在问题没有修复之前,修改不会被提交。
到这里,提交的代码质量基本上已经能得到很好的保证。
还有最后一个问题:每次commit时都会全量检查或者修复所有的代码,这不仅仅耗时,并且假如哪些并非我们修改的代码有格式问题,我们也不得不修正后同时提交,尽管它们和我们本次迭代没有任何关系(commit噪音)。
我们希望仅仅只校验我们修改过的文件,无关代码格式暂时不管。
lint-staged
解决上面的问题,同样可以编写git脚本处理,但是难度依然不小,lint-staged则让这件事儿变得简单。
- 安装
npm install -D lint-staged
- 在packages.json的scripts中添加命令
"lint-staged": "lint-staged"
- 修改
.husky/pre-commit
下的npm命令为npm run lint-staged
- 项目根目录下创建
.lintstagedrc
配置文件,内容如下:
{
"*.(tsx|js|ts|jsx)": "eslint --fix",
"*.(md|json|less)": "prettier --write"
}
此时,再次提交commit时,pre-commit钩子执行npm run lint-staged
命令,lint-staged
找到.lintstagedrc
配置文件,对git暂存区的文件,根据文件类型,执行相应的命令。这里对(tsx|js|ts|jsx)
这几种文件执行eslint的修复命令(也包括了prettier的规则,因为prettier是作为eslint的插件运行的),对(md|json|less)
类型文件执行prettier的修复命令,你可以根据需要自行定义。
和上面一样,假如格式校验失败,commit提交失败,区别在于校验的是全量代码还是Git暂存区。
至此,一个满足项目基本需求的代码校验工具链就搭建起来了,个中细节可以按自己的需求定制。
最后,水平所限,难免有错误和不严谨的地方,欢迎指正。
参考
- Automagically lint and format your code
- Using Prettier and ESLint to automate formatting and fixing JavaScript