ESLint配置详解
ESLint
是一个代码检查工具,用来检查代码是否符合指定的规范,防止在多人协作开发时代码格式不统一。
安装
全局安装
npm install eslint -g
当前项目安装
npm install eslint -D
安装之后运行eslint --init
进行初始化,使用eslint --init
会根据命令配置好一个模板.eslintrc.*
文件。
当然也可以手动创建一个.eslintrc.*
(支持后缀请看下面的配置文件部分)文件。
TODO 如果你想使用托管在 npm 上的指定可共享配置,你可以使用 --config 选项并指定包名:
执行eslint xxx
命令对文件夹下的所有js
文件或者单独某个js
文件(指定文件名)进行校验。
配置文件
配置文件格式
ESLint
支持几种格式的配置文件:
js
(一般都是使用该后缀)cjs
yaml
json
同时可以在package.json
文件添加eslintConfig
配置。
如果在同一目录下存在多个配置文件,ESLint
将按照以下优先顺序只使用其中一个(并不会进行合并配置):
.eslintrc.js
.eslintrc.cjs
(需要在package.json
中指定"type":"module"
).eslintrc.yaml
.eslintrc.yml
.eslintrc.json
package.json
配置文件的使用
通常情况下ESLint
都是使用在根目录下创建的.eslintrc.*
文件,不过也可以通过指令指定配置文件。
eslint -c eslintConfig.js myfile.js
如果指定了配置文件,如果没有设置忽略的话,那么同时要校验的文件同目录及父目录下的.eslintrc.*
都会生效(详情看下面的级联和层级结构)。
设置忽略只需在命令后添加--no-eslintrc
eslint -c eslintConfig.js myfile.js --no-eslintrc
级联和层次结构
ESLint
会自动在要检查文件的目录中寻找( .eslintrc.*
和 package.json
文件),并在其直系父目录中寻找,直到文件系统的根目录(/)、当前用户的主目录(~/)或指定 root: true
时停止。
比如创建了以下结构的目录
root
├── .eslintrc.js
├── src
│ └── index.js
└─┬ tests
├── .eslintrc.js
└── test.js
在根目录下执行eslint src
,src
目录没有.eslintrc.*
或者package.json
文件,因此往父目录上找,找到root/.eslintrc.js
这个文件,因此执行这个配置。
在根目录下执行eslint tests
,tests
目录存在一个.eslintrc.js
文件(在合并时优先考虑),继续找父目录,也存在一个.eslintrc.js
文件,ESLint
会将这两个配置文件进行合并。
配置级联的工作是基于被提示的文件的位置。如果有一个
.eslintrc
文件与被提示的文件在同一目录下,那么该配置将被优先考虑。然后ESLint
沿着目录结构向上搜索,合并沿途发现的任何.eslintrc
文件,直到到达root: true
的.eslintrc
文件或根目录。
如果在同一目录下有 .eslintrc.*
和 package.json
文件,.eslintrc.*
将优先使用,package.json
文件将不被使用
扩展配置文件
可以使用extends
字段(详情请看下面的rules/extends
部分)来继承另一个配置文件的特征(包括规则、插件和语言选项)并修改所有选项。它有三种配置,定义如下:
- 基础配置:被扩展的配置。
- 派生配置:扩展基础配置的配置。
- 实际配置:将派生配置合并到基础配置的结果。
字段详解
在.eslintrc.*
文件中可以配置多种字段,下面来看看对每个字段的详细介绍:
root
默认情况下,ESLint
将在所有父文件夹中寻找配置文件,直到根目录(所有这些配置文件的规则都会被层叠应用。若有重复的属性配置,则离文件更近的配置文件具有更高的优先级)。要将 ESLint
限制在一个特定的项目中,在 .eslintrc.*
文件或 package.json
文件的 eslintConfig
字段内或在项目根层的 .eslintrc.*
文件中设置 "root": true
。一旦 ESLint
找到 "root": true
的配置,它将停止在父文件夹中寻找。
因此建议当想要所有项目都遵循一个特定的规则时,最好给项目根目录的.eslintrc.js
文件加上"root": true
配置。
rules
规则是 ESLint
的核心构建模块。
ESLint
有大量的内置规则(例如:no-console
、no-var
这些),开发者可以通过配置注释或配置文件来修改项目使用到的规则,也可以通过插件添加更多规则。
规则配置
规则的设置值必须为以下几个:
off
或者0
: 关闭规则warn
或者1
: 启用并视作警告(不影响退出)。error
或者2
: 启用并视作错误(触发时退出代码为1
)。
来个简单例子看看具体的区别:
规则就设置一个no-console
,测试的js
文件中就一行console.log('eslint')
- 当
off
或者0
的时候eslint
校验通过。 - 当
warn
或者1
的时候会有一个警告,但是程序并未退出,继续打印done
。
- 当
error
或者2
的时候在打印出错误后直接退出程序。
使用配置注释
可以单独在文件中进行配置(以注释的方式)
/* eslint no-console: "warn" */
console.log('eslint');
插件规则
要配置定义在插件中的规则,你必须在规则 ID
前加上插件的名称和 /
{
plugins: ["plugin1"],
rules: {
"plugin1/rule1": 2
}
}
规则 plugin1/rule1
来自名为 plugin1
的插件,包含在名为 eslint-plugin-plugin1
的 npm
包中。
禁用规则
我们在开发的过程中,有时候不想使用某些规则,可以使用配置注释禁用规则。
/* eslint-disable */
console.log("eslint")
/* eslint-enable */
注释内的所有代码不需要任何规则,在js
文件的第一行添加则整个文件都禁用规则。
/* eslint-disable no-alert, no-console */
alert('eslint');
console.log('eslint');
/* eslint-disable no-alert, no-console */
单独禁用某些规则。
console.log('eslint'); // eslint-disable-line
// eslint-disable-next-line
console.log('eslint');
console.log('eslint'); /* eslint-disable-line */
/* eslint-disable-line */
console.log('eslint');
禁用某一特定行的规则。
/* eslint-disable-line no-console */
console.log('eslint');
单独禁用某一特定行的某些规则。
plugins
plugin
插件主要是为eslint
新增一些检查规则,虽然ESLint
本身有些规则,但肯定无法包含所有语法,比如vue
、react
这些,因此ESLint
是支持自定义规则的。
来看看eslint-plugin-vue
源码,里边定制了一些eslint
规则。
那么对于新增加的规则,如果想要在项目中使用,需要进行以下步骤:
- 安装对应的
ESLint
插件(比如eslint-plugin-vue
) - 加载插件(在
plugins
中配置,赋予ESLint
解析插件规则的检查能力),然后在rules
中开启规则。
module.exports = {
plugins: [
'eslint-plugin-vue'
],
rules: {
'eslint-plugin-vue/no-v-html': 2
}
}
plugins
属性值可以省略包名中的 eslint-plugin-
前缀,也就是说可以直接通过vue
引入
"plugins": "vue",
extends
用于引入继承其他配置包中配置,然后通过合并/覆盖所有原本的配置生成最终的规则(extends
可以看做是集成多个配置方案的方式,配置的内容实际就是配置好的.eslintrc.js
,不然对于每一个项目都要重新一步步开始选择配置规则就比较显得不太人性)。
extends
的属性值可以是:
- 定义一个配置的字符串(配置文件的路径、可共享配置的名称,如
eslint:recommended
或eslint:all
)。 - 字符串数组,每个扩展都会先继承前面一个扩展的配置(允许
extends
配置多个模块,如果规则冲突,位置靠后的包将覆盖前面的。rules
中的规则相同,并且优先级恒定高于extends
,类似class
的extends
,支持多继承)。
extends
属性值由以下内容组成:
plugin
:- 包名(可以省略其前缀,如
vue
是eslint-plugin-vue
的缩写) - /
- 配置名称(如
recommended
)
TODO 暂时未确定
插件包名的格式一般是eslint-plugin-<plugin-name>
,就像 eslint-plugin-vue
,也可能是含命名空间包的格式@<scope>/eslint-plugin-<plugin-name>
,例如 @vue/eslint-config-prettier
,甚至 @<scope>/eslint-plugin
,如@jquery/eslint-plugin
。
下面是引入了vue3
的配置:
"extends": "plugin:vue/vue3-essential",
eslint-plugin-vue
里实现了多种配置规则,为了方便其他人使用,它默认实现了最佳实践recommened
,原先还需要自己一条条选择,这样就可以直接把官方配置好的最佳实践直接拿来用。如果碰到和自己风格或者规范有冲突的规则,那直接在rules
中重新定义就可以了。
插件实现扩展配置流程
通过extends设置的配置包加载的时候,是递归的形式去查找配置文件然后一步步派生继承的。
env
env
用于指定代码运行的环境。在不同的运行环境下,JavaScript
中可用的全局变量可能会不同,使用 env
可以让 ESLint
知道当前代码运行的环境,从而正确地识别全局变量,避免误报未定义变量等问题。
常见的 env
(查看所有env
) 配置如下:
browser
:浏览器环境,可以使用浏览器中的全局变量如window
、document
等。node
:Node.js
环境,可以使用Node.js
中的全局变量如process
、Buffer
等。commonjs
:CommonJS
环境,可以使用CommonJS
模块中的变量如module
、require
等。es6
:ES6
环境,可以使用ES6
中的全局变量如Set
、Map
等。jest
:Jest
测试框架环境,可以使用Jest
中的全局变量如describe
、test
等。
parser
自定义解析器,从其他类型的文件中提取 JavaScript
代码,或在提示前对代码进行预处理。
也可以使用自定义解析器将 JavaScript
代码转换成抽象的语法树,供 ESLint
评估。如果你的代码与 ESLint
的默认解析器 Espree
(ESLint
默认解析器) 不兼容,可能需要添加自定义解析器。
像@typescript-eslint/parser
就是把typescript
转换为与 ESTree
兼容的形式的解析器。
parser: '@typescript-eslint/parser'
parserOptions
用于指定想要支持的js
语言选项,Eslint
默认使用 ECMAScript 5
语法,不过可以通过parserOptions
来覆盖语法。
可配置值为:
ecmaVersion
- 设置为 3、5(默认)、6、7、8、9、10、11、12 或 13,以指定你要使用的ECMAScript
语法的版本。你也可以设置为 2015(6)、2016(7)、2017(8)、2018(9)、2019(10)、2020(11)、2021(12)或 2022(13)来使用基于年份的命名。你也可以设置"latest"
来使用受支持的最新版本。sourceType
- 设置为"script"
(默认值)或"module"
(如果代码是ECMAScript
模块)。allowReserved
- 允许使用保留字作为标识符(如果ecmaVersion
为 3)。ecmaFeatures
- 表示你想使用哪些额外的语言特性的对象。-
globalReturn
- 允许全局范围内的return
语句
-
impliedStrict
- 启用全局严格模式(如果ecmaVersion
是 5 或更高版本)
-
jsx
- 启用JSX
overrides
对于同一目录下的文件而已,使用的配置基本都是同一份,不过ESLint
也提供了一个可以用于让同一目录下的文件使用不同配置的方式。
在 overrides
中提供配置,这些配置只会用于符合特定 glob
模式的文件,且使用与你在命令行中传递的相同格式(如 src/*.js
)。
{
rules: {
'no-console': 2,
'no-alert': 2
},
overrides: [
{
files: ['src/*.js'],
excludedFiles: ["src/index.js"],
rules: {
"no-console": 0
}
}
]
}
以上的配置是在src
目录下的所有文件(除了index.js
)都可以使用console.log
而不会报错,因为overrides.rules
中的no-console: 0
规则覆盖掉了rules
中的no-console: 2
,而no-alert: 2
没有被覆盖,仍会生效。
以下是几点overrides
的工作方式:
- 在同一配置文件中,
glob
模式覆盖的优先级高于常规配置。同一个配置文件中的多个覆盖会按顺序应用。也就是说,配置文件中的最后一个覆盖块总是具有最高的优先权。 - 针对
glob
的配置与其他ESLint
配置的工作原理几乎相同。覆盖块可以包含任何在常规配置中有效的配置选项,但root
和ignorePatterns
除外。 -
- 一个
glob
特定的配置可以有一个extends
设置,但扩展配置中的root
属性会被忽略。扩展配置中的ignorePatterns
属性只用于glob
特定配置所匹配的文件。
- 一个
-
- 嵌套的
overrides
设置只有在父配置和子配置的glob
模式都匹配时才会被应用。当扩展的配置设置了overrides
时也是这样。
- 嵌套的
- 在覆盖块中可以提供多个
glob
模式。一个文件必须至少与所提供的模式之一相匹配,才能使用该配置。 - 覆盖块也可以指定排除在匹配之外的模式。如果一个文件与任何一个被排除的模式相匹配,则不会使用该配置。
ignorePatterns
通过配置 glob
匹配模糊让 ESLint
在检查时忽略明确的文件或目录。
可以使用下列方法忽略文件:
- 在配置文件中添加
ignorePatterns
。 - 创建包括忽略匹配模式的专用文件(默认为
.eslintignore
)。
{
ignorePatterns: ['src/*.js']
}
注意:
ignorePatterns
中的glob
模式是相对于配置文件所在的目录而言的。- 不能在
overrides
属性中使用ignorePatterns
属性。 - 在
.eslintignore
中定义的模式优先于配置文件的ignorePatterns
属性
使用.eslintignore
.eslintignore
文件是一个纯文本文件,其中每一行都是一个 glob
模式,表示哪些路径应该被省略掉。
当运行
ESLint
时,在决定要检查的文件范围前,它会在当前工作目录中寻找.eslintignore
文件。如果找到该文件,那么在遍历目录时就会应用这些偏好。每次只能使用一个.eslintignore
文件,且仅会使用当前工作目录中的.eslintignore
文件。
Glob
使用 node-ignore
进行匹配,因此有许多特性:
- 以
#
开头的行被视为注释,不影响忽略模式。 - 路径是相对于当前工作目录的。这也适用于通过
--ignore-pattern
命令传递的路径。 - 前面有
!
的行是否定模式,会重新包含被先前模式忽略的模式。 - 忽略模式的行为与
.gitignore
规范一致。
# 忽略所有的 JavaScript 文件
**/*.js
# 有效路径
/app/src/*.js
# 无效路径 路径必须使用正斜杠作为路径分隔符
\app\src\*.js
# src/test.js没有忽略,src/下其他js文件会被忽略
src/
!src/test.js
使用替代文件
通过 --ignore-path
选项可以配置其他目录下的.eslintignore
文件(并且文件名不需要局限于.eslintignore
)。
eslint --ignore-path .jshintignore file.js
错误修正
ESLint
提供了几个选项来尝试修复问题:
--fix
指示ESLint
尝试修复尽可能多的问题。这些修复是对实际文件本身进行的,只有剩余的未修复的问题才会被输出。
当然不是所有的问题都可以通过这个选项修复的,以下情况并不适用:
- 当代码通过
pipe
传递给ESLint
时会抛出错误。 - 此项对使用处理器的代码没有影响,除非处理器选择了允许自动修复。
--fix-dry-run
此项与--fix
的效果相同,但有一点不同:修复后的代码不会保存在文件系统中。因为默认格式不输出修复后的代码,你必须使用另一种格式(如json
)来获得修复内容。
这使得从 stdin
中修复代码成为可能(当与 --stdin
标志一起使用时)。
getSomeText | npx eslint --stdin --fix-dry-run --format=json
--fix-type
用于在使用 --fix
或 --fix-dry-run
时指定应用的修复类型。
有四种修复类型(可同时配置多个):
problem
- 修复代码中的潜在错误suggestion
- 改进代码layout
- 修复不改变程序结构(AST
)的问题directive
- 修复内联指令,如 // eslint-disable
npx eslint --fix --fix-type suggestion .
npx eslint --fix --fix-type suggestion --fix-type problem .
npx eslint --fix --fix-type suggestion,layout .