You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
module.exports={rules: {// The following rules can be used in some cases. See the README for more information. // (These are marked with `0` instead of `"off"` so that a script can distinguish them.)"curly": 0,"lines-around-comment": 0,"max-len": 0,"no-confusing-arrow": 0,"no-mixed-operators": 0,"no-tabs": 0,"no-unexpected-multiline": 0,"quotes": 0,"@typescript-eslint/quotes": 0,"babel/quotes": 0,"vue/html-self-closing": 0,"vue/max-len": 0,// The rest are rules that you never need to enable when using Prettier."array-bracket-newline": "off",// ...}}
本文并非旨在介绍 Linters 及其周边工具的具体使用方式,而是详细介绍它们之间的关系和基本原理,并探究更优雅的配合方式。这一切都先从 ESLint 开始:
ESLint
ESLint 是现在最流行 JS Linter,它的运行原理是通过解析器将源代码解析成 AST,ESLint 在遍历 AST 过程中会遍历到每个选择器,ESLint 每条规则定义时都会返回一个或者多个以选择器为 key 的回调函数,选择器被遍历到则会执行对应的回调以检测代码是否符合规则。
通常以配置文件的形式配置规则:
parser
: 解析器,默认使用 Espree。如果你使用了 Babel 或者 TypeScript,则需要配置对应的解析器完成代码解析,比如babel-eslint
、@typescript-eslint/parser
。extends
: 开启一系列规则。比如设置eslint:all
将开启 ESLint 所有规则,eslint:recommended
则仅开启eslint
官方推荐的一些规则。也可以安装并使用更严格的社区规则,比如airbnb。rules
: 修改单条规则的错误级别或关闭规则。配置解析器并开启一些检查规则后即可对 JavaScript 代码进行检查。
ESLint 中的两类规则
由于 ESLint 中存在两类规则:
no-unused-vars
(禁止出现未使用过的变量)。max-len
(每行代码最大长度)、comma-style
(逗号风格)、keyword-spacing
(关键字前后空格)等。所以执行
eslint .
命令除了会检测出代码质量问题,还会报告代码格式问题。前者是它最核心的功能。ESLint 在有
--fix
选项之前 ESLint 不能自动修复格式问题,因为代码格式并不存在错误或潜在的问题,但这类错误却往往非常多,为了解决这一个头疼的问题,引入了 Prettier,它专门用于统一代码风格。当 ESLint 有了--fix
之后依然不能完全替代Prettier
。Prettier 与 ESLint
ESLint 不能完全替代
Prettier
的原因在于 Prettier 不仅仅可以是 JavaScript 的代码格式化工具,它还支持格式化JSX
、Vue
、TypeScript
、CSS
、Less
、SCSS
、HTML
、Markdown
...如果你想统一项目中所有代码的编码风格,ESLint 能做到的并不全面,所以通常是 ESLint 捕获 JS 代码错误,Prettier 格式化代码(包括 JS 的部分)。下面是 Prettier 的配置文件:
eslint-config-prettier
由于 ESLint 存在代码格式规则,而且其中部分规则与 Prettier 中的规则存在冲突。
当确定了 ESLint 捕获 JS 代码错误、Prettier 格式代码的分工原则之后,ESLint 中的代码格式规则已经不再必要,
eslint-config-prettier
的作用就是关闭这些不必要且可能会与 Prettier 发生冲突的规则:eslint-config-prettier
是一个预设配置,是多个规则的集合,原理就是将这些规则全部设置为设置0
或"off"
,添加到extends
选项的尾部实现覆盖。由于这些规则并不影响代码质量的检测,所以覆盖后不会有问题。eslint-plugin-prettier(不推荐)
关闭 ESLint 的代码格式规则之后,JS 代码的格式化就全部交由 Prettier。但会有些人期望 JS 代码质量和代码格式的错误都通过 ESLint 来报告,
eslint-plugin-prettier
的作用就在于此。插件增加了一条
prettier/prettier
规则,并使用 prettier 对代码风格进行检查,先使用 Prettier 对代码进行格式化,并与格式化前的代码进行对比,出现不一致的地方就会被 Prettier 标记。若prettier/prettier
规则开启则 Prettier 并将错误信息通过 ESLint 报告。eslint-plugin-prettier
同样需要预先关闭 ESLint 中的代码格式规则,所以需要配合eslint-config-prettier
一起使用,因此它附带了一个plugin:prettier/recommended
配置,通过此配置可以一次性完成与eslint-config-prettier
的配置:不推荐的原因:
个人认为不推荐的最主要原因是第一点,实际开发中通常希望能及时发现代码中的质量问题,而不是等到代码提交时再发现并需要进行修改甚至改造,因为这会导致需要重新测试代码逻辑。所以通常的做法是使用IDE插件或者构建工具插件实时报告代码质量规则问题,如VSCode ESLint 插件)和
eslint-webpack-plugin
](https://github.com/webpack-contrib/eslint-webpack-plugin)。而代码格式问题并不应该在开发过程中看到的,如果集成eslint-plugin-prettier
将导致编辑器中或控制台中出现很多无关紧要的代码风格提示,这十分影响开发体验。所以对于代码格式问题最好的办法不是需要实时面对并修复它们,而是能忘记代码的格式化。VSCode ESLint 插件:读取目录下的 ESLint 配置文件,对代码进行检查后提示错误,可通过配置开启文件保存时自动修复(但没必要)。
tslint-config-prettier、tslint-plugin-prettier
stylelint 场景下也存在一个预设+插件,同样是解决冲突和在 lint 中调用 Prettier,后面会提到。
prettier-eslint、prettier-tslint、prettier-stylelint
有人想到在 ESLint 调用 Prettier(
eslint-plugin-prettier
),就有人想用 Prettier 调用 ESLint,于是就有了prettier-eslint
。prettier-eslint
解决的问题是:如果没有禁用 ESLint 中的代码格式规则,Prettier 格式化后的代码很可能无法通过 ESLint。所以通常的做法是先使用prettier --write
格式化后再经过eslint --fix
处理。prettier-eslint
的作用就是将这两个步骤合二为一,原理就是将被 Prettier 格式化后的代码传递给 ESLint 执行eslint --fix
。对于 ESlint 无法处理的扩展名文件则只运行 Prettier,如.css
,.less
,.scss
或.json
。同样的思路诞生了 prettier-tslint、prettier-stylelint。
Git Hooks
上面提到处理代码格式问题的最好的办法是忘记代码的格式化。通常的做法是代码提交时,利用 Git 钩子在提交前自动修复代码格式问题。
Git Hooks 保证 Git 在特定的重要动作发生时触发自定义脚本。项目
git init
之后将初始化一个.git
目录,在.git/hooks
目录下默认会填充很多后缀为.sample
的示例 shell 脚本,这些就是对应钩子执行的 shell 样本文件,将文件名中的后缀.sample
去掉后即可执行,你可以可以自定义脚本内容并正确命名放入.git/hooks
目录下。这些脚本除了本身可以被调用外,还透出了被触发时所传入的参数。常用的 Git Hooks:
pre-commit
:git commit
执行前触发。通常用于检查代码风格是否一致,如 lint 程序。commit-msg
:git commit
执行前触发。通常用于校验提交信息是否规范。husky
在
.git/hooks
目录下添加 shell 脚本并非特别方便,所以husky
的作用就是让我们更简单的在项目中添加 Git Hooks,它只需要像添加 npm 脚本一样使用 Git Hooks。husky@4
husky@4
及其之前的版本,你只需要在package.json
中加入类似如下配置即可在代码提交时自动完成代码的格式化:husky@4
的工作原理是在.git/hooks
下创建所有类型的 Git Hooks 和一个husky.sh
脚本,所有 Git Hooks 执行脚本的内容都是执行husky.sh
(内容如下👇🏻)。husky.sh
的程序内容就是去检查用户在package.json#husky.hooks
是否配置了对应的钩子,有则执行。这也导致 Git 每个特定动作都将执行 husky 设置的脚本,即使用户没有设置任何 Git Hooks。这个问题并不好解决,如果不事先创建所有类型的 Git Hooks,用户在后续添加或者删除
package.json#husky.hooks
的配置时,husky 没有好的办法做到同步删除或者添加.git/hooks
目录下的 hook。只有用户 hooks 配置和 Git Hooks 在同一个地方才能解决同步问题。
新版本 husky
Git 2.9 引入了
core.hooksPath
的新功能,它允许指定 Git Hooks 执行脚本的存放的目录,而不再必须使用.git/hooks
目录。这就可以解决了husky@4
存在的问题。新版的 husky 使用husky install
命令将 Git Hooks 目录指定为.husky/
,使用husky add
命令向.husky/
中添加 hook。用户后续直接操作.husky/
目录的 hook 即完成增删改操作,也就不再有同步问题。添加钩子:
package.json
配置:pretty-quick 和 lint-staged
通常情况下我们并不希望对项目所有代码进行格式化,这会导致当前提交存在大量的修改难以 Code Review;格式化工具还可能存在未知 bug 导致无效代码,这类问题除非大范围回归否则难以发现。所以我们更希望仅对当前修改的代码文件进行格式化。
pretty-quick
和lint-staged
的作用就是允许我们仅对 Git 暂存区的文件上执行特定脚本,他们通常都与husky
配合使用。pretty-quick
pretty-quick
是对更改的文件运行 Prettier,本身仅格式化暂存区的文件。--staged
的作用是格式化后的代码会重新暂存,即相当于执行了git add .
。执行上述命令后lint-staged
lint-staged
并不与 Prettier 存在绑定关系,所以需要在package.json#lint-staged
字段添加格式化命令。Stylelint
Stylelint 顾名思义是样式代码规范校验工具。类似
ESLint
它同样包含代码质量和代码格式两类规则,使用--fix
选项自动修复检测出来的问题。下面是一简单的配置文件:stylelint-config-standard
: 官网推荐的 CSS 标准。stylelint-config-recess-order
: 属性排列顺序,保证代码更好地可读性。stylelint-config-prettier
: 为了解决 Prettier 与 Stylelint 的规则冲突,关闭 Stylelint 中所有代码格式规则。放在extends
选项最后以确保覆盖其他配置。使用:
VSCode Stylelint 插件:读取 Stylelint 配置文件,对代码进行检查后提示错误,可通过配置开启文件保存时自动修复(但没必要)。
stylelint-prettier(不推荐)
类似
eslint-plugin-prettier
,stylelint-prettier
的作用也是将 prettier 代码风格规则应用于 stylelint。同样的,它最好与stylelint-config-prettier
配合使用。EditorConfig 与 Prettier
EditorConfig 有助于同一项目下使用不同 IDE 的多个开发人员维护一致的编码风格。
EditorConfig 还存在一些与 Prettier 冲突的配置项,应避免出现重复配置。
Prettier
会解析.editorconfig
文件,并将仅限以下配置项转换为 Prettier 中对应的默认配置,覆盖的前提是 Prettier 配置文件中配置对应选项:end_of_line
: 对应 Prettier 中的endOfLine
,指定行结束符。indent_style
: 对应useTabs
,表示是否使用tab缩进。indent_size
/tab_width
: 对应tabWidth
,表示tab缩进大小。max_line_length
: 对应printWidth
,表示每行最大字符数。commitlint
commitlint 也是 Linters 家族中的一员,用于校验 commit message 是否符合提交格式(通常为
type(scope?): subject
)。参考
The text was updated successfully, but these errors were encountered: