About
ESLint 是一款开源的 JavaScript lint 工具,由 Nicholas C. Zakas 于2013 年创建。
ESLint 官方文档 About 页面 分 About 和 Philosophy 两个部分对 ESLint 做了介绍,简洁明了,值得一读。
借助 ESLint,可将 静态代码分析 和 问题代码协助修复 集成到 编码、提交 和 打包 过程中,及早发现并协助修复代码中:
- 有语法错误的部分
- 不符合约定的样式准则的部分
- 不符合约定的最佳实践的部分
在项目开发中获得如下收益:
- 在执行代码之前发现并修复语法错误,减少调试耗时和潜在 bug
- 保证项目的编码风格统一,提高可维护性
- 督促团队成员在编码时遵守约定的最佳实践,提高代码质量
安装
# Local Installation
yarn add -D eslint
# Global Installation
yarn add -g eslint
复制代码
注意
- ESLint 借助 nodejs 的模块化机制引用插件。所以,全局安装的 ESLint 只能使用全局安装的 ESLint 插件,局部安装的 ESLint 只能使用局部安装的 ESLint 插件。
命令行接口
官方文档:eslint.org/docs/user-g…
命令模式
# eslint [选项] [操作目标]
eslint [options] [file|dir|glob]*
复制代码
注意
-
当使用
glob
语法指定操作目标时,glob
模式会被shell
解析,解析结果可能因shell
不同而不同。如果想要使用node
的glob
语法,必须使用引号将glob
模式串引起来(在 Windows 中必须使用双引号)。示例:eslint "lib/**" 复制代码
命令选项
使用 ESLint 命令时,可以通过 eslint -h
概览命令选项,找到自己需要的选项,然后后去官方文档 命令行接口部分 查看该选项的详细描述。
有些选项可接收一组参数,这类选项支持两种传参方式(有一个选项例外:--ignore-pattern
不支持第二种方式):
- 多次指定同一选项,每次接收一个不同的参数
- 将参数列表用逗号分隔,一次传给选项
示例:
# 1.
eslint --ext .jsx --ext .js lib/
# 2.
eslint --ext .jsx,.js lib/
复制代码
配置
相对路径解析
配置文件中包含的相对路径和 glob 模式都是基于当前配置文件的路径进行解析的。
两种主要的配置方式
- 配置注释 - 在目标文件中使用注释语法嵌入配置信息。这种配置只对当前文件有效。
- 配置文件 - 在
JavaScript
、JSON
或YAML
文件中定义配置信息。对于这种配置方式,配置信息可以写在单独的.eslintrc.*
文件中,或者写在package.json
文件的eslintConfig
字段中。这种配置对配置文件所在目录及其子目录树中的所有文件有效。
配置文件格式
JavaScript
- use.eslintrc.js
文件导出一个包含配置信息的对象。YAML
- 使用.eslintrc.yaml
或.eslintrc.yml
定义配置。JSON
- 使用.eslintrc.json
定义配置信息,JSON 文件中支持 JavaScript 注释。package.json
- 在package.json
文件中增加一个eslintConfig
字段,在该字段中定义配置信息。.eslintrc
- 已废弃
如果在同一个目录中有多个配置文件,则它们中间只有一个是有效的,优先级如下:
.eslintrc.js
.eslintrc.yaml
.eslintrc.yml
.eslintrc.json
.eslintrc
package.json
配置层叠
官方文档:eslint.org/docs/user-g…
项目级配置文件
在同一个项目中,可以为不同目录指定不同的配置文件。
当 lint 一个文件时,ESLint :
- 从文件所在目录开始,在目录树中依次向上搜索配置文件,直到系统根目录,或者直到找到一个包含
root: true
配置参数的配置文件,最终得到一个配置文件列表。 - 合并上一步得到的配置文件列表中的配置项,得到最终的配置文件配置。合并配置项时,在目录树中距离 lint 目标越近的配置文件具有越高的优先级。
- 执行其余步骤。
完整的配置层叠关系
ESLint 配置除了通过配置文件指定,还可以通过注释内嵌或命令行选项指定。Lint 一个文件所使用的最终配置是各种配置合并的结果,合并时各种配置的优先级如下:
-
注释内嵌配置
/*eslint-disable*/
and/*eslint-enable*/
/*global*/
/*eslint*/
/*eslint-env*/
-
通过命令行选项指定的配置
--global
--rule
--env
-c
,--config
-
项目级配置文件
-
如果没有找到项目级配置文件,并且没有或没有找到通过
--config
指定配置文件,则去用户家目录(~/
)下搜索配置文件。
如果上述配置均不存在,则 ESLint 抛出 noConfigError
。
配置参数
-
parser
指定 ESLint 使用的语法分析器。ESLint 兼容的语法分析器有:Esprima、Babel-ESLint、@typescript-eslint/parser,ESLint 默认使用 Esprima。
-
parserOptions
指定语法分析器选项,默认使用的语法分析器支持如下几个选项:
ecmaVersion
、sourceType
、ecmaFeatures
。示例:{ "parserOptions": { "ecmaVersion": 6, "sourceType": "module", "ecmaFeatures": { "jsx": true } } } 复制代码
不同的语法分析器可能具有不同的选项。
-
env
指定执行环境,一个执行环境会预定义一组全局变量。示例:
使用注释配置
/* eslint-env node, mocha */ 复制代码
使用配置文件:
{ "env": { "browser": true, "node": true } } 复制代码
-
globals
使用未在当前文件中定义的全局变量时,会命中
no-undef
规则,通过globals
配置指定的全局变量无视no-undef
规则。示例:使用注释配置
/* global var1, var2 */ /* global var1:writable, var2:writable */ 复制代码
在配置文件中指定:
{ "globals": { "var1": "writable", "var2": "readonly" } } 复制代码
-
plugins
插件是第三方定制的规则集合,
plugins
参数用于指定第三方插件,插件名中的eslint-plugin-
前缀可以省略。示例:{ "plugins": [ "plugin1", "eslint-plugin-plugin2" ] } 复制代码
使用插件时必须安装其 npm 包。
注意
- 受限于 Node 的模块化机制,全局安装的 ESLint 只能使用全局安装的插件,局部安装的 ESLint 只能使用局部安装的插件,不支持全局插件和局部插件的混合使用。
-
rules
指定 ESLint 校验规则。
所有规则独立于其他规则,可单独配置。
ESLint 内置规则:eslint.org/docs/rules/
规则组成:规则名、错误级别、附加选项
规则配置模式:
规则名: [错误级别, 附加选项] 规则名: 错误级别 复制代码
示例:
"rules": { "semi": ["error", "always"], "quotes": ["error", "double"] } 复制代码
在上述示例中,
"semi"
和"quotes"
是规则名,"error"
是规则错误级别,"always"
和"quotes"
分别是semi
和quotes
各自特有的附加选项。ESLint 定义了三种错误级别:
"off"
或0
- 关闭,不校验该规则"warn"
或1
- 警告,不影响 exit code"error"
或2
- 错误,触发该规则时 exit code 为1
关于规则的错误级别,在 ESLint 特性概览 部分已有介绍。
使用注释配置
/* eslint eqeqeq: "off", curly: "error" */ // 如果规则有额外选项,可以用数组字面量语法 /* eslint quotes: ["error", "double"], curly: 2 */ 复制代码
使用配置文件
{ "rules": { "eqeqeq": "off", "curly": "error", "quotes": ["error", "double"] } } 复制代码
可在文件中使用注释配置禁用全部规则或指定规则:
-
块级禁用
/* eslint-disable */ alert('foo'); /* eslint-enable */ /* eslint-disable no-alert, no-console */ alert('foo'); console.log('bar'); /* eslint-enable no-alert, no-console */ 复制代码
-
文件级禁用
/* eslint-disable */ alert('foo'); /* eslint-disable no-alert */ alert('foo'); 复制代码
-
在指定行中禁用
alert('foo'); // eslint-disable-line alert('foo'); // eslint-disable-line no-alert alert('foo'); // eslint-disable-line no-alert, quotes, semi alert('foo'); /* eslint-disable-line */ alert('foo'); /* eslint-disable-line no-alert */ alert('foo'); /* eslint-disable-line no-alert, quotes, semi */ // eslint-disable-next-line // eslint-disable-next-line no-alert // eslint-disable-next-line no-alert, quotes, semi /* eslint-disable-next-line */ /* eslint-disable-next-line no-alert */ /* eslint-disable-next-line no-alert, quotes, semi */ alert('foo'); 复制代码
-
overrides
示例:
{ "rules": {...}, "overrides": [ { "files": ["*-test.js","*.spec.js"], "excludedFiles": "*.test.js", "rules": { "no-unused-expressions": "off" } } ] } 复制代码
对于匹配
overrides.files
且不匹配overrides.excludedFiles
的 文件,overrides.rules
中的规则会覆盖rules
中的同名规则。 -
settings
指定一个对象,这个对象会被提供给每一个将要执行的规则。
-
root
ESLint 在目录树种搜索配置文件时,若遇到
root
参数为true
的配置文件,就会停止搜索,否则沿着目录树一直向父级目录的方向搜索到系统根目录为止。 -
extends
配置文件可以在已有配置的基础上进行扩展,
extends
用于指定基础配置。该参数的值为以下之一:- 一个指定基础配置来源的字符串
- 一个指定基础配置来源的字符串的数组:数组中每个配置扩展它前面的配置
ESLint 支持递归扩展配置,所以基础配置中也可包含
extends
参数。当指定基础配置时,
rules
参数指定的规则可按如下几种方式进行扩展:- 启用基础配置中没有规则
- 继承基础配置中的规则,改变其错误级别,但不改变其附加选项:
- 基础配置:
"eqeqeq": ["error", "allow-null"]
- 扩展配置:
"eqeqeq": "warn"
- 最终有效配置:
"eqeqeq": ["warn", "allow-null"]
- 基础配置:
- 覆盖基础配置中的规则:
- 基础配置:
"quotes": ["error", "single", "avoid-escape"]
- 扩展配置:
"quotes": ["error", "single"]
- 最终有效配置:
"quotes": ["error", "single"]
- 基础配置:
使用
extends
指定的基础配置来源可以是:-
eslint:recommended
,启用 ESLint 内置规则集 的一个子集。 -
共享配置包,一类导出 ESLint 配置对象的 npm 包,比如
eslint-config-standard
、eslint-config-airbnb
等。共享配置包需要安装才能使用,配置时可省略报名中的eslint-config-
前缀。示例:
{ "extends": ["airbnb"] "rules": { "no-set-state": "off" } } 复制代码
-
插件导出的命名配置,其配置值由以下几部分组成:
plugin:
- 插件包名(可省略前缀,例如:
react
) /
- 配置名(例如:
recommended
)
示例:
{ "plugins": [ "react" ], "extends": [ "eslint:recommended", "plugin:react/recommended" ], "rules": { "no-set-state": "off" } } 复制代码
-
配置文件,通过配置文件的绝对路径或相对路径指定。
示例:
{ "extends": [ "./node_modules/coding-standard/eslintDefaults.js", "./node_modules/coding-standard/.eslintrc-es6", "./node_modules/coding-standard/.eslintrc-jsx", "./my-eslint-config.js" ], "rules": { "eqeqeq": "warn" } } 复制代码
-
eslint:all
,启动所有 ESLint 内置规则,不推荐。
-
忽略文件和目录
使用
.eslintignore
文件指定要忽略的文件和目录,忽略模式的指定使用.gitignore
的 规范。ESLint 默认忽略
/node_modules/*
和/bower_components/*
。示例:
# /node_modules/* and /bower_components/* in the project root are ignored by default # Ignore built files except build/index.js build/* !build/index.js 复制代码
基于 eslint-config-airbnb 扩展配置
eslint-config-airbnb 是一个 ESLint 共享配置包,支持 ECMAScript 6+ 和 React。
安装 eslint-config-airbnb
# 安装 eslint-config-airbnb
yarn add -D eslint-config-airbnb@latest
# 获取 peerDependencies
npm info "eslint-config-airbnb@latest" peerDependencies
# 安装 peerDependencies
yarn add -D @ @ ...
复制代码
eslint-config-airbnb 依赖的插件
- eslint-plugin-import - 支持 ES6+
import
/export
语法以及模块路径有效性的校验。 - eslint-plugin-react - 支持 React 编码规范的校验。
- eslint-plugin-jsx-a11y - 支持 HTML 元素可访问性的校验。
配置示例
// .eslintrc.js
module.exports = {
root: true,
extends: ['airbnb'],
parserOptions: {
// eslint-config-airbnb: { ecmaVersion: 6, sourceType: 'module' }
ecmaFeatures: {
// eslint-config-airbnb: { jsx: true, es6: true }
generators: true,
},
},
env: {
// eslint-config-airbnb: { node: true, es6: true }
browser: true,
},
rules: {
indent: ['error', 4],
},
}
复制代码
使用 eslint-import-resolver-webpack
如果开启了 eslint-plugin-import no-unresolved
规则,可以借助该插件使用 webpack 的 resolve
配置解析模块路径。
安装
yarn add -D eslint-import-resolver-webpack
复制代码
配置方式:
{
"settings": {
"import/resolver": "webpack", // 使用 webpack 默认配置
}
}
复制代码
{
"settings": {
"import/resolver": {
"webpack": {
"config": "webpack.dev.config.js" // 指定要使用的 webpack 配置文件
}
}
}
}
复制代码
{
"settings": {
"import/resolver": {
"webpack": {
"config": { // 定义 webpack 配置对象
"resolve": {
"extensions": [".js", ".jsx"]
}
}
}
}
}
}
复制代码
使用 babel-eslint
babel-eslint 是一款用于 ESLint 的语法分析器,它支持使用 ESLint 分析所有 babel 兼容的代码。
使用 babel-eslint 需要安装 babel 并提供 babel 配置文件。
ESLint 核心规则不支持实验阶段的语法,如果要使用这部分语法,需要配合 eslint-plugin-babel 使用。
安装
# 安装 babel-eslint
yarn add -D babel-eslint
# 安装 eslint-plugin-babel
yarn add -D eslint-plugin-babel
复制代码
配置
{
"parser": "babel-eslint",
"plugins": ["babel"]
}
复制代码
集成
VSCode 集成
代码提示
工具:VSCode ESLint 插件
使用:在 VSCode 设置中将 eslint.enable
设置为 true
代码修复
工具:VSCode Prettier 插件
使用:在 VSCode 设置中将 prettier.eslintIntegration
设置为 true
,prettier 插件执行格式化时将使用 prettier-eslint 完成下述操作:
- 使用 prettier 格式化代码
- 对上一步格式化过的代码执行
eslint --fix
相比于直接使用 eslint --fix
命令,prettier 插件:
- 支持快捷键
- 支持更多的代码格式化选项
- 支持其他类型文件的格式化
git commit 集成
在提交代码时,lint git 暂存区的代码,若 lint 不通过则中断提交,保证问题代码不进入代码仓库。
工具:
- husky - 提供 git hooks 支持
- lint-staged - 对暂存文件(staged files)中匹配指定 glob 模式的文件执行指定的 shell 命令。
配置示例:
package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"linters": {
"**/*.js": ["eslint --fix", "git add"]
},
"ignore": ["**/{dist,build}/**/*.js", "**/*.min.js"]
}
}
复制代码
其他集成
eslint.org/docs/user-g…
完整配置示例
module.exports = {
root: true,
extends: ['airbnb'],
plugins: ['babel'],
parser: 'babel-eslint',
parserOptions: {
ecmaFeatures: {
generators: true,
},
},
env: {
browser: true,
},
rules: {
indent: ['error', 4],
},
settings: {
'import/resolver': {
// 识别 webpack 配置的路径别名
webpack: {
config: 'webpack.config.js',
}
},
},
}
/**
peerDependencies: {
"babel-eslint": "^10.0.1",
"eslint": "^5.15.0",
"eslint-config-airbnb": "^17.1.0",
"eslint-import-resolver-webpack": "^0.11.0",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.1",
"eslint-plugin-react": "^7.11.0",
}
*/
复制代码