大家好,我是编程小6,很高兴遇见你,有问题可以及时留言哦。
env
globals
parserOptions
parser
rules
plugins
extends
overrides
ignorePatterns
Lint(Linter) 是一种静态代码分析工具,用于标记代码中某些编码错误、风格问题和不具结构性(易导致 bug)的代码。简单理解就是一个代码检查器,检查目标代码是否符合语法和规定的风格习惯。 ESLint 是基于 ECMAScript/JavaScript 语法的 Lint,能够:
ESLint 的特点是灵活、高度自定义,用户可以通过多种方式配置在项目中应用的规则和其它配置,也可以自定义自己的规则,还可以通过插件的方式拓展功能。
在项目中使用 ESLint 对个人、团队的帮助都是显著的。
现在,即使团队内没有形成统一的规范,在工程化项目中大部分会使用 ESLint 来帮助检查、统一项目中的代码。
前提:Node.js(>=12.0.0) 且项目目录中存在 package.json 文件。
npm install --save-install eslint
npx eslint --init
# 注:npx 表示从当前路径下查找命令,即 ./node_modules/.bin/eslint --init
ESLint 会询问一系列问题,根据你的回答生成对应的.eslintrc.*
配置文件。
/* $ npx eslint --init ✔ How would you like to use ESLint? · style ✔ What type of modules does your project use? · esm ✔ Which framework does your project use? · react ✔ Does your project use TypeScript? · No / Yes ✔ Where does your code run? · browser ✔ How would you like to define a style for your project? · guide ✔ Which style guide do you want to follow? · standard ✔ What format do you want your config file to be in? · JSON */
// 上面的回答对应下面的 .eslint.json 文件
{
"env": {
"browser": true,
"es2021": true
},
"extends": ["plugin:react/recommended", "standard"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": ["react", "@typescript-eslint"],
"rules": {}
}
(配置部分内容较多,而且简单上手无需太深入配置,后面会先说 ESLint 的使用,最后再总结配置内容)
注:现在已经很少在命令行使用 eslint 了,一般都通过编辑器插件的方式与编辑器配合使用,实现在编辑的过程中实时检查。这种方式可以稍微了解,加深理解。
npx eslint [file|dir|glob]*
, 入:# 检查多个文件
npx eslint file1.js file2.js
# 使用 glob 正则,检查目录下所有文件
npx eslint lib/**
--fix
选项自动 fix 可修复问题,如:# index.js 中可自动修复的问题会被修复并忽略
npx eslint --fix index.js
更多命令和参数,参看 ESLint Docs: Command Line Interface,这里不深入。
注:除了 VSCode,其他编辑器也有对应的 ESlint 集成方式,参看 ESLint Docs: Integrations。
首先,安装 VSCode ESlint 插件。 需要注意,插件并不内置 ESLint 核心代码,而是自动查找项目中的 ESLint 库,在用户每次输入时调用lint
命令,并在编辑器中标记代码问题,文档这样说明:
The extension uses the ESLint library installed in the opened workspace folder. If the folder doesn't provide one the extension looks for a global install version.
这样的好处是,编辑器能兼容不同项目中不同版本的 ESLint,同时,能保证同一项目中,团队成员的 ESLint 版本一致。
如果希望在每次保持时,自动 fix 可修复问题,可以在 VSCode 中设置保存时 fix:
/* * VSCode Settings JSON File */
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
}
配置文件是 ESLint 最主要的配置方式。ESLint 配置文件支持多种格式,同一目录下,ESLint 按 .eslintrc.js
, .eslintrc.cjs
, .eslintrc.yaml
, .eslintrc.yml
, .eslintrc.json
, package.json 下的 eslintConfig 字段
的顺序查找配置,相同目录下只有一个配置文件会生效。其中,常用的是eslintrc.[js|json]
格式,下文采用 eslint.json
格式。
ESLint 还支持使用注释更灵活、细粒度地对特定文件、局部代码进行配置,常常用于复写特殊代码片段的规则。
ESLint 配置的主要内容包括 执行环境 env
、全局变量 globals
、规则 rules
。
我们知道,不同的执行环境会向 JavaScript 注入不同的全局变量,如浏览器中的window
,Node.js 的process
。另外,不同的 ECMAScript 语法版本支持的语法和特性有所不同。因此,代码的合法性是与执行环境和环境支持的 ES 版本相关的。
为了 ESLint 能正确识别代码是否规范合法,我们必须配置代码的执行环境和支持的语法选项。
env
ESLint 默认不开启任何环境,可以在env
字段下使用"env_name":true
的方式开启,环境之间不会互斥,可以同时开启多个环境,如:
{
"env": {
"browser": true,
"node":true,
"es6":true
}
}
开启环境后,ESLint 能正常解析代码中的全局变量,可能还会开启对应的语法解析选项。常见的环境有:
browser
: 浏览器全局变量。node
: Node.js 全局变量和作用域。es6
: 支持 ES6 语法(不含 ES module),并开启 ES6 语法解析选项。完整的环境列表,参看 ESLint Docs: Specifying Environments。
globals
env
可以方便地支持特定环境下的全局变量,但 JavaScript 的执行环境要复杂得多,每个模块和外部依赖都有可能注入自己的全局变量,为了避免这被识别成错误,需要在配置中指出代码中用到的外部全局变量。 globals
字段用于设置代码中的全局变量,语法为{"var_name": "off"|"readonly"|"writable"}
, 如:
{
"globals":{
"$":"readonly",
"globalState":"writable"
}
}
"off"
的作用在于关闭env
带来的全局变量,如在支持大部分 ES2015 语法,但不支持 Promise 的浏览器中,可以设置:
{
"env":{
"es6": true
},
"globals":{
"Promise":"off"
}
}
parserOptions
在 ESLint 解析的时候提供一些语言特性的支持,如 ES 语法、JSX。ESLint 默认支持 ES5 语法。
配置语法语法如下:
{
"parserOptions":{
/* ecmaVersion: 指定 ECMA 语法版本 * 取值: * - "latest": 使用最新版本,现在 (2021) 等同于 12 * - 版本号:3, 5(默认), 6, 7, 8, 9, 10, 11, 12 * - 年份命名法:2015(=6), 2016(=7), 2017(8) ... */
"ecmaVersion": "latest",
/* sourceType: 脚本类型,普通脚本 或 ES 模块脚本 * 取值:"script"(默认) | "module"(ES 模块脚本) */
"sourceType":"module",
/* ecmaFeatures: 支持的特性语法*/
"ecmaFeatures": {
// 支持在全局使用 return
"globalReturn": true,
// 默认使用严格模式(ES 5 或 以上)
"impliedStrict": true,
// 支持 JSX 语法
"jsx": true
}
}
}
需要注意的是,开启更高的 ES 解析选项并不会自动支持对应的 ES 全局变量。所以,为了支持最新的 ES 语法:
{
"env":{
// 支持 es 语法全局变量识别,这是必须的
"es2021": true,
},
/* 下面是可选的,因为 es2021 会自动设置 "ecmaVersion": 12 "parserOptions": { "ecmaVersion": 12 } */
}
parser
ESLint 默认使用的是 Espree 解析器。你也可以通过parser
字段使用其他解析器。 解析器需要满足两个条件:
如果项目中用到一些语言增强工具(TypeScript、Babel)或者框架(React、Vue),就需要使用与之对应的解析器。 以 TypeScript 为例,为了正确解析代码,你需要:
.eslintrc.json
对应的目录下安装解析器npm install --save-dev @typescript-eslint/parser
{
"parser": "@typescript-eslint/parser"
}
注:使用其他插件时,parserOptions
仍然有效,它会作为参数传递给解析器。
rules
rules
是 ESLint 中最重要的配置,里面规定了将采用哪些规则去约束代码。
ESLint 提供了大量的 内置规则。此外,使用插件可以添加适合特定场景下的规则集。
规则的配置语法是{"rules": {"rule_name": state | [state, ...options] }}
, 其中,state
代表枚举值:
"off"
或者 0
: 关闭规则,常用于关闭某个来自extends
中的规则。"warn"
或者 1
: 规则校验不通过时发出 warning 提示。"error"
或者 2
: 规则校验不通过时发出 error 提示,返回 1,表示 lint 检查不通过。下面的配置方式都是合法的:
{
"rules":{
// 使用 "off", "warn", "error"
"no-console": "warn",
// 使用数字(不推荐,语义不明确)
"for-direction": 1,
// 数组语法,但没有额外配置项
"no-else-return": ["error"],
// 数组语法,一个配置项
"eqeqeq":["error","always"],
// 数组语法,多个配置项
"quotes": ["error", "double", { "avoidEscape": true }]
}
}
plugins
ESLint 支持第三方插件的使用,使用前,需要先在配置文件的目录上安装对应的 npm 包。
安装插件之后,就可以在 ESLint 的plugins
数组中添加该配置文件需要使用的插件。不过,插件的各项规则配置都是默认关闭的,所以plugins
只是使用插件功能的前提,你必须在rules
,extends
,env
中开启你需要的规则特性。
{
"plugins":["jest"],
"extends": ["plugin:jest/recommended"],
"env":{
"jest/global":true
},
"rules":{
"jest/valid-expect": "error"
}
}
ESLint 对插件的命名做了规定:
eslint-plugin-<plugin-name>
缩写 <plugin-name>
: 如eslint-plugin-jquery
缩写 jquery
。@<scope>/eslint-plugin-<plugin-name>
缩写 @<scope>/<plugin-name>
: 如 @jquery/eslint-plugin-jquery
缩写 @jquery/jquery
。@<scope>/eslint-plugin
缩写 @<scope>
: 如 @jquery/eslint-plugin
缩写 @jquery
。一般使用不含 eslint-plugin
的简写形式。
ESLint 使用 <plugin-name>/XXX
的方式指定插件内的规则或其他配置。根据 ESLint Docs: Working with Plugins, 一个插件能带来:
{"rules": {"react/boolean-prop-naming": "warning"}}
。{"env": {"jest/global": true}}
。{"extends": ["plugin:react/recommended"]}
。{"process": "a-plugin/a-processor"}
。extends
使用extends
能很方便地继承已有配置的全部特性,包括rules
, env
, extends
等。
配置继承与面向对象中“类的继承”类似。如果称被继承配置为“父配置”,继承配置为“子配置”,那么子配置具有父配置的所有特性,并且可以在子配置中的规则会覆盖父配置的同一规则。配置继承也具有传递性。
配置的继承极大方便了项目之间通用配置的共享,也避免了每次繁琐的大量规则配置。
extends
数组包含了配置中继承的所有父配置,当只有一个父配置时,也可以使用{"extend": "config-name"}
的形式。
父配置可以通过几种方式指定:
"eslint:recommended"
和 "eslint:all"
。"eslint-config-<config-name>"
, 命名及其缩写和插件命名类似。如{
"extends": ["standard"] // 同 eslint-config-standard
}
"plugin:a-plugin/config"
, plugin:
前缀为了区分简写下的配置和插件包名。如{
// 别忘了 plugins
"plugins": ["react"],
"extends": ["plugin:react/recommended"]
}
{"extends": "./.my-eslintrc.json"}
。overrides
overrides
支持通过 Glob 模式 匹配特定文件集合,额外应用不同的配置。比如,我们经常需要在项目中根据文件类型应用不同的规则。
overrides
是一个配置对象数组,里面的对象支持大部分的 ESLint 配置,而且多了用于匹配文件的 files
数组和 excludedFiles
数组。当对文件进行 lint 检查时,目标文件相对于配置文件的相对路径会与这两组 glob 模式进行匹配,如果路径满足files
中任何一个,且不满足excludedFiles
中任何一个模式,则会被应用该配置。
/* ./src 目录下除了 a.js 下的 js 文件应用 no-alert 规则 */
{
"overrides": [
{
"files": ["src/*.js"],
"excludedFiles": "a.js",
"rules": {
"no-alert": "warn"
}
}
]
}
ignorePatterns
ignorePatterns
数组包含了一组 glob 模式,当文件路径匹配其中任意一个时被忽略,作用类似.gitignore
。
一般都不希望对打包产物进行 lint 检查:
{
"ignorePatterns": ["**/dist/**", "**/output/**"]
}
除了文件配置,ESLint 还支持使用注释进行文件内的配置,这种方式更灵活,一般作为补充。
注:如果通过命令行执行,还能通过命令参数注入配置,这里不讨论。
ESLint 注释区分//
和/**/
, 可以在注释的同时说明原因,原因放在配置内容之后,用两个或两个以上 -
隔开。
常用的注释:
/* * 单行关闭 */
alert('foo'); // eslint-disable-line
// eslint-disable-next-line -- I don't want eslint
alert('foo');
/* eslint-disable-next-line */
alert('foo');
alert('foo'); /* eslint-disable-line */
// eslint-disable-next-line no-alert, quotes, semi
alert('foo');
foo(); // eslint-disable-line plugin/rule-name
/* * 块关闭 */
/* eslint-disable */
console.log("bar")
alert('foo');
/* eslint-enable */
/* eslint-disable no-alert, no-console */
alert('foo');
console.log('bar');
/* eslint-enable no-alert, no-console */
/* * 整个文件关闭,在第一行使用 eslint-disable */
/* eslint-disable */
alert('foo');
//...
/* eslint-disable no-alert */
alert('foo');
//...
/* eslint quotes: ["error", "double"], curly: 2 ----- 字符串内容含有'', 不想用转移和模版字符串 */
const foo="'bar'"
// var1 只读,var2 读写
/* global var1, var2: writable */
/* eslint-env node, mocha */
尽管一个目录下只有一个配置文件会生效,但 ESLint 支持在不同目录层级下放置多个配置文件。执行文件 lint 时,会从当前文件的目录开始,逐级往上查找配置文件,直到根目录或 遇到{"root": true}
的配置,并合并不同层级的配置。
注:应该在项目根目录下设置 {"root": true}
避免不必要的查找和影响。
由于 ESLint 支持多处配置,配置之间可能会冲突,需要规定优先级:
overrides
> rule
> extends
当多个地方的rules
配置出现相同规则时,
如果该规则没有配置选项(只支持错误等级),则简单应用最高优先级。
如果该规则支持额外配置选项,且高优先级的规则配置没提供选项,则继承低优先级的选项;否则,只应用高优先级的配置和选项。如:
"eqeqeq": ["error", "allow-null"]
+ "eqeqeq": "warn"
(高优先级) = "eqeqeq": ["warn", "allow-null"]
"quotes": ["error", "single", "avoid-escape"]
+ "quotes": ["error", "single"]
(高优先级) = "quotes": ["error", "single"]