彻底搞清楚ESLint和Prettier的职责关系

·  阅读 2095

Linters的功能概述

ESLint、StyleLint、TSLint(已废弃)都属于Linters,它们通过对代码的AST进行分析,并按照一系列可配置的规则,为用户提供代码校验的功能。他们的规则主要分为两大类:Formatting Rules和Code-quality Rules。

通常,Linters的客户端还会提供修复功能(--fix),我们常用的IDE借助这些客户端便可以实现代码自动修复的功能。那么,既然Linters已经可以自动修复了,为什么我们还要用Prettier。

Linters没有解决的问题

Linters的自动修复是基于上述两种规则:Formatting和Code-quality。在Code-quality上,Linters做的做够好了,像no-unused-varsno-extra-bindno-undef等。但是在Formatting上,Linters虽然能在一定程度上保证代码的格式,像max-lenno-mixed-spaces-and-tabskeyword-spacing等, 但是在书写工业化代码的时候,我们会有更高的要求:保证团队的代码风格完全一致。举个例子:

在不超出max-len的条件下,如下两种写法Linters都是允许的:

// 小明写的
const {a, b, c} = obj
// 小李写的
const {
	a,
  b,
  c,
} = obj
复制代码

这就导致在仅使用Linters的进行格式化场景下,一个团队写出的代码可能千人千面,这其实不满足我们对于工业化代码的要求。但是如果使用Prettier,最终的格式化效果只会是这两种其中的一种。

Prettier的功能概述

Prettier是一个多语言支持的代码格式化工具,它也是通过AST解析代码,然后以一个特定的格式输出格式化后的代码。相比Linters,Prettier没有那么多针语言语法的规则,而是一个纯粹的代码格式化工具,在Prettier看来,任何东西都是可以格式化的。

因此,Prettier和Linter在代码格式化的思路上是不一样的:

  • Linters的格式化思路是:给我一个规则,如果不符合这个规则,我才会去格式化。

  • Prettier的格式化思路是:给我一个规则,如果不符合这个规则,我按照A格式格式化,如果符合这个规则,我按照B格式格式化。

按照上述思路,举个例子,相比于上面的max-len,Prettier的printWidth逻辑会有所不同:

  • max-len:如果不超过这个长度,Linters就不会格式化;如果超过了这个长度,会格式化。

  • printWidth:如果不超过这个长度,按照A格式格式化;如果超过了这个长度,按照B格式格式化。

所以在这个过程中,代码的风格差异性被抹除了,不管你怎么写,Prettier格式化后的代码格式总是一样的。

Linters和Prettier之间是否会有冲突?

是的,在Formatting Rules上会有冲突。举个例子,如果max-len设为100,而printWidth设为120,而你写的代码长度为110,这个时候这两个规则就会冲突。因此我们需要一些措施来解决这个问题。

配合使用Linters和Prettier

有两种思路:

  1. 先用Prettier格式化,再用Linters格式化

  2. 使用Linters按照Prettier的规则格式化(最佳实践)

对于第1种思路,一般是使用prettier-eslint这个库,按照code -> prettier -> eslint --fix的流程格式化代码,因此它不得不格式化两次才能完成操作,会有性能问题,所以目前已经不推荐这个方案了。

接下来主要讨论第2种思路:使用Linters按照Prettier的规则格式化

代码格式化的最佳实践

Prettier将会作为Linters中Formatting Rules的完全替代品参与到代码格式化的过程中。为了达成这个目标,我们有两件事需要做:

  1. 禁用掉Linters中所有与Prettier冲突的Formatting Rules

  2. 针对Prettier自身的规则,使用Prettier进行格式化

这两件事需要分别借助两个库来实现,为了方便分析,我们以JS代码格式化为例:

在这里需要理解eslint-config-xxx和eslint-plugin-xxx的区别:

  • eslint-config-xxx: 表示一系列可以被继承的eslint规则
  • eslint-plugin-xxx: 表示一个功能的具体实现代码

有了这两个库,在稍微修改一下eslint配置即可:

module.exports = {
  plugins: ['prettier'], // eslint-plugin-prettier的缩写
  extends: [
    'prettier', // eslint-config-prettier的缩写
  ],
  rules: {
    'prettier/prettier': 'error'
  }
}
复制代码

因此,使用Linters+Prettier进行代码格式化的最佳实践套路即是:-plugin-prettier + -config-prettier,不同语言之间大同小异。

参考

prettier.io/docs/en/int…

jlongster.com/A-Prettier-…

eslint.org/docs/rules/

完。

分类:
前端
标签: