相信做前端开发都碰到过Eslint,经常被它搞的痛苦不堪,其实它并没有那么复杂,今天咱们好好聊聊。
首先,我们从基础出发来看看 EsLint 相关配置代表的含义。
配置文件
在 EsLint 中所有的检测规则都是可配置的,自然所有的配置规则都需要有一个配置的存储文件。
在 EsLint 中支持两种方式来进行规则配置:
- Configuration Comments 在你的 JavaScript 代码中直接使用 JS 注释的形式将配置嵌入你的原代码。
-
Configuration Files 使用单独 Eslint 配置文件来整合你的相关配置,支持 JavaScript、JSON 或者 YAML 文件三种格式(
.eslintrc.*
),当然也可以直接将配置写入项目的package.json
中。在调用 EsLint 命令时,Eslint 会自动寻找对应的配置文件。
同时在 EsLint 中配置文件也支持向上查找的方式(层叠配置),比如我们的项目定义目录如下所示:
层叠配置使用离要检测的文件最近的 .eslintrc
文件作为最高优先级,然后才是父目录里的配置文件。
这也就意味这,在 projectA 项目中不仅仅 projectA/.eslintrc.js 中的配置规则会生效,同时它也会继承上一层目录中的 .eslintrc 的配置(.eslintc.js)。
默认情况下,ESLint 会在所有父级目录里寻找配置文件,一直找到根目录。少部分情况下如果我们想要你所有项目都遵循一个特定的约定时,这将会很有用。(比如在 monorepo 项目中,我们通常会存在一份根级别的 EsLint 配置文件约束)。
同时,当寻找到项目根目录的 eslintrc.js
时,我们希望它停止向上查找。那么此时 Eslint 的配置文件也支持设置 root: true
的选项来停止这种层叠配置的查找机制。
比如,如果在 demo/packages/projectA/.eslintrc.js
中设置了 root: true
,那么此时 projectA/index.js
仅会有 projectA/eslintrc.js
的配置生效。
demo/.eslintrc.js
仅会影响 projectB/index.js
并不会影响 packageA/index.js
。
ParserOptions
EsLint 支持任何类型的 JavaScript 语言选项(比如 ES6、模块类型等等),默认不进行任何配置时 EsLint 默认检测规则为 ES5 代码,
我们可以通过配置中的 ParserOptions 选项来进行语言选项设置,比如:
文章之后的例子都会以
.eslint.js
的配置文件方式来演示。
上述的 Eslint 配置文件中,我们没有设置任何 ParserOptions。默认会使用 ES5 规范来检查我们的代码,自然当我们在项目中使用 const
时,EsLint 会提示错误 const
作为保留关键字。
当然,我们可以使用 ParserOptions 来修改 EsLint 对于语法检测的规则:
当然 ParserOptions 中支持的全部配置选项:
-
ecmaVersion
: 如上边示例的,表示应用代码中支持的 ECMAScript 版本。默认为 5 ,支持3、5、6、7、8、9 或 10 来指定你想要使用的 ECMAScript 版本。当然也可以使用latest
表示最新的 ECMA 版本。 -
sourceType
: 表示应用代码中支持的模块规范,默认为script
。支持script
和module
(ESM) 两种配置。 -
ecmaFeatures
: 它是一个对象,表示代码中可以使用的额外语言特性。
- globalReturn 允许全局下使用 return 。
- impliedStrict 启用全局严格模式。(ES 5以上有效)
- jsx 允许代码中使用 jsx 语法。
总之,ParserOptions
选项表示 EsLint 对于不同的 Parser(解析器)配置的语言检查规则。
Parser
上边我们提到所谓的 ParserOptions 代表 Eslint 中支持我们使用哪些语法。
在 EsLint 配置中有一个和它名称非常相似的配置 Parser
,它表示 Eslint 在解析我们的代码时使用到的解析器。
关于 EsLint 是如何帮助我们进行代码检查的,简单来说本质上它仍是将我们的代码根据规定的解析器转化成为 AST 抽象语法树。
之后根据我们传入配置中的各种规则对于源代码生成的 AST 语法树进行代码检查以及代码修复。
ESLint 默认情况下使用Espree作为其解析器,当然我们也可以传入一些自定义的解析器。
通常,我们在项目中使用 typescript 代码:
上述我们使用了 typescript 语法定义了变量 b 但是并没有使用变量 b ,此时 EsLint 规则检查并没有生效。
这是因为我里上述配置文件的 parser
默认使用的是 espree
,它并不支持 typescript
语法的检查,要额外支持 ts
语法的检查需要使用额外的 ts 解析器。
我们提到过本质上 ESLint 内部是基于 AST 进行检查,对于 AST 想深入了解的同学可以查看我这篇文章。
所以 tsc 在处理 ts 语法转译后的 ast 规则是 eslint 默认的 espree 是完全不一致的,所以我们需要通过 @typescript-eslint/parser 解析器来解析我们的代码。
当我们使用特定的解析器时,比如使用 @typescript-eslint/parser 最终会将 ts 文件转移后的 ast 结构转化成为 espree 支持的 ast 结构进行静态检查。
当然,我们最开始提到的 parserOptions 也是针对于不同的解析器(Parser)的选项配置,具体各个 ParserOptions 选项内容可以在不同的 parser 文档中查找对应规则。
所以,Parser 选项简单来说就是表示我们以何种解析器来转译我们的代码。本质上,所有的解析器最终都需要讲代码转化为 espree
格式从而交给 Eslint 来检测。