利用Prettier & Eslint & Husky & lint-staged规范代码的操作指引

lxf2023-05-07 11:02:01

本文主要涉及如下几个方面:

  1. 如何让Prettier和Eslint两个校验工具协同合作,对代码进行校验和格式化。
  2. 如何配置Vscode,利用Prettier和Eslint的规则实现保存时自动格式化。
  3. 如何利用Husky和lint-staged,实现Git commit提交之前,对Git暂存区代码实现校验和格式化。

1、 Why Both Prettier & Eslint

Prettier和Eslint两者都能校验且修改代码格式,为什么同时需要这两个工具?

  1. 两者关注点侧重不一样,Prettier 只关注代码格式,Eslint 侧重语法检查,同时带有格式检查。
  2. Prettier 不针对具体语言,且开箱即用。eslint 针对特别的语言需要特别的配置。

前端项目中,js、ts、tsx 等可以使用 eslint 校验和格式化,其他如 htmlcss 等可以交给开箱即用的 Prettier 来处理

2、 Eslint 安装配置

如果是在已有 eslint 配置的项目基础上改造,可以跳过这一小节

  1. 执行npm install eslint --save-dev
  2. 项目根目录下创建.eslintrc.eslintignore,并根据项目需要配置。你也可以根据自己的喜好选择配置文件的格式。本文主要关注点在 eslint 和 prettier 的协作上,所以关于 eslint 的详细配置还请参考其文档。你完全可以在已经配置有 eslint 的项目基础上继续下面的实操试验。
  3. packages.json的 script 中添加如下两条命令:
{
  "lint": "eslint",
  "lint:fix": "eslint --fix"
}

3、 安装配置 prettier

  1. 执行npm install prettier --save-dev
  2. 在根目录下新建.prettierrc文件,该文件是Prettier规则的配置文件,每一条对应一个规则,举例如下:
{
  "semi": false,
  "singleQuote": true
  // 其他规则
}

同样该文件也支持多种格式,可根据自己的喜好选择。

添加该文件后, vscode setting.json 配置中,以prettier.开头的私人规则将不会生效。后续在工具自动格式化代码时,如果发现与预期不符,可以来这里修改相关规则。

如果想忽略某些文件检查,可以在根目录下添加.prettierignore配置文件,写入希望忽略的文件路径。

  1. 添加命令 在packages.json的scripts中添加如下两条命令:
{
  "prettier": "prettier src --check",
  "prettier:fix": "prettier src --write"
}

prettier命令用于检查src文件夹下所有文件的格式,prettier:fix则格式化src文件夹下所有文件的格式。

到目前为止,我们有eslint和prettier两种处理代码格式的工具,但两者各自为政,没有很好的协同合作,甚至在有些地方两者的规则还有可能冲突,所以还需要进一步配置让两者协同起来。

4、 eslint和prettier协同

  1. 安装eslint-plugin-prettier

npm install eslint-plugin-prettier --save-dev

eslint-plugin-prettier是一个eslint插件,它能将Prettier作为eslint的插件调用

  1. eslint配置

在 eslintrc 的 plugins 配置中加入 prettier 插件:

{
  "plugins": ["prettier"]
}

5、 处理冲突

两个工具都有代码格式校验的规则,相互之间有冲突,可使用eslint-config-prettier来处理,该eslint扩展关掉了和prettier相冲突的eslint规则,保证一致性。

  1. 安装:npm install eslint-config-prettier -D
  2. eslintrc 配置如下,注意 prettier 配置的位置:
{
  // ❗prettier一定要放在extends列表的最后
  "extends": ["xxx", "prettier"],
  "plugins": ["prettier"]
}

6、 vscode 配置

  1. 插件及配置

vscode 插件搜索eslintesbenp.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.formatOnSaveeditor.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

  1. 安装npm install husky -D
  2. packages.json的scripts中添加"prepare": "husky install"
  3. 执行npm run prepare。此时,你的项目根目录会多出一个.husky文件夹
  4. .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则让这件事儿变得简单。

  1. 安装npm install -D lint-staged
  2. 在packages.json的scripts中添加命令"lint-staged": "lint-staged"
  3. 修改.husky/pre-commit下的npm命令为npm run lint-staged
  4. 项目根目录下创建.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暂存区。

至此,一个满足项目基本需求的代码校验工具链就搭建起来了,个中细节可以按自己的需求定制。

最后,水平所限,难免有错误和不严谨的地方,欢迎指正。

参考

  1. Automagically lint and format your code
  2. Using Prettier and ESLint to automate formatting and fixing JavaScript