为啥要用ESLint?
团队成员代码风格不同,水平各异。如果允许成员任意发挥,随意coding,不做任何约束的话,随着项目规模慢慢变大,项目代码将很有可能成为难以维护的屎山。所有对于代码的基本写法需要有约束,当代码编写不合约束时能给出提醒,同时能自动修复,这些正是ESLint 要做的事情。
- 找出代码中不符合规范的地方,报出异常或错误,给出提示
- 能自动修复 不合规的代码
- 自定义规则
ESLint 如何工作?
ESLint 是如何读懂代码,甚至自动修复不合规代码呢?关键是AST(抽象语法树),其中 ESLint 是使用espree来生成 AST 的。
ESLint 会遍历 AST,然后在遍历到不同的节点或特定的时机的时候,触发相应的处理函数,在处理函数中抛出错误、提示。
ESLint 流程大致分为 读取配置、加载配置、检验、修复。
读取配置
ESLint 首先会从各种配置文件中读取配置,例如 eslintrc
或package.json
中的eslintConfig
字段中,或使用命令行执行 eslint 时指定任意一个配置文件
先读取给定目录下最近的配置文件
相同目录存在多个配置文件,仅有一个配置文件会被读取,
.eslintrc
优先级的配置文件会高于package.json
配置内层目录没有,会默认向外层文件夹逐层读取配置文件, 可通过在配置文件添加
root:true
来阻止逐层读取如果多个配置文件里都配置了重复字段的话,离给定目录最近的配置会生效
加载配置
ESLint会依次加载配置里的extends
,parser
,plugin
等,其中
-
extends
是其他配置文件,可以复用插件中的配置或者第三方模块中的配置
ESLint 会递归地去读取配置文件中的extends
,最终各个配置对象的顺序是[{内层配置},{内层配置的extends},{外层配置},{外层配置中的extends}],之后会进行合并操作,具体合并逻辑
对于 parser、processor字段,后面的配置会覆盖前面的配置
对应 env、globals、parserOptions,settings 字段会合并在一起,但只有当后面的配置存在,而前面的没有该字段时,这个字段才会被合并进来,如果前面有,那么后面的相同自读会被摒弃
对应 rules,前面的配置优先级高,如果存在的rule里有参数,参数会被合并
parser
用于解析ASTplugin
是用户自定义的插件,可映入自定义规则,以及对非js文件的检查和处理等
检查
当获得所有需要的配置后,接下来就会进入检验流程,大致执行顺序
处理 processor
processor 是在插件上定义的处理器,并针对特定后缀文件定义preprocess 和 postprocess 两个方法。
preprocess方法接受文件源码和文件名作为参数,返回需要被检测的代码或文件的数组。
postprocess 在文件被检验完后,对所有的lint problem 进行统一处理
解析代码, 获取AST 和 节点 数组,没有指定parser时,默认使用 espress
跑规则 runRules
ESLint 的核心就是处理一条一条的规则,如何处理?
- 收集AST所有的节点
- 遍历所有配置中的rule,并通过rule的名称找到对应的rule对象。ESLint 会为rule对象里的AST节点添加相应的监听函数,以便在后面遍历AST节点时可以出发相应的处理函数
- 再次遍历收集的AST节点,出发相应的节点监听函数,在监听函数中调用方法收集所有的eslint 问题
修复
ESLint 的 rule 对AST进行检查,并报错。fixer 则根据 AST节点中保留的 range 信息(源码的下标范围)来修改代码