爱客仕-前端团队博客园

ESLint

Eslint官网:http://eslint.cn/docs/user-guide/configuring

写在前面

在团队协作中,为避免低级 Bug、产出风格统一的代码,会预先制定编码规范。使用 Lint 工具和代码风格检测工具,则可以辅助编码规范执行,有效控制代码质量。

ESLint 简介

ESLint是一个QA工具,用来避免低级错误和统一代码的风格。以可扩展、每条规则独立、不内置编码风格为理念编写一个 lint 工具。
ESLint 由 JavaScript 红宝书 作者 Nicholas C. Zakas 编写。
ESLint 主要有以下特点:

  • 默认规则包含所有 JSLint、JSHint 中存在的规则,易迁移;
  • 规则可配置性高:可设置「警告-1」、「错误-2」两个 error 等级,或者直接「禁用-0」;
  • 包含代码风格检测的规则(可以丢掉 JSCS 了);
  • 支持插件扩展、自定义规则。

使用 ESLint

ESLint 详尽使用参见 官方文档 ,下面罗列的是由 JSHint 迁移到 ESLint 的一些要点。

全局和本地安装eslint

  • npm install eslint -g
  • npm install eslint -save-dev

配置

可以通过以下三种方式配置 ESLint:
1.使用 .eslintrc 文件(支持 JSON 和 YAML 两种语法);
2.在 package.json 中添加 eslintConfig 配置块;
3.直接在代码文件中定义。

.eslintrc 文件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"env": {
"browser": true
},
"globals": {
"angular": true
},
"rules": {
"camelcase": 2,
"curly": 2,
"brace-style": [2, "1tbs"],
"quotes": [2, "single"],
"semi": [2, "always"],
"space-in-brackets": [2, "never"],
"space-infix-ops": 2
}
}

.eslintrc 放在项目根目录,则会应用到整个项目;如果子目录中也包含 .eslintrc 文件,则子目录会忽略根目录的配
置文件,应用该目录中的配置文件。这样可以方便地对不同环境的代码应用不同的规则。

package.json 示例:

1
2
3
4
5
6
7
8
9
10
{
"name": "mypackage",
"version": "0.0.1",
"eslintConfig": {
"env": {
"browser": true,
"node": true
}
}
}

文件内配置

代码文件内配置的规则会覆盖配置文件里的规则。
禁用 ESLint:

1
2
3
/* eslint-disable */
var obj = { key: 'value', }; // I don't care about IE8
/* eslint-enable */

禁用一条规则:

1
2
3
/*eslint-disable no-alert */
alert('doing awful things');
/* eslint-enable no-alert */

调整规则:

1
2
3
/* eslint no-comma-dangle:1 */
// Make this just a warning, not an error
var obj = { key: 'value', }

自定义语法规则

显然,ESLint 内置的规则不可能包罗所有需求。可以通过插件实现自定义规则在 NPM 上以 eslintplugin 为关键
词,可以搜索到很多插件,包括 eslint-plugin-react 。如果有自行开发插件的需求,可以阅读
ESLint 插件开发文档

以 eslint-plugin-react 为例,安装以后,需要在 ESLint 配置中开启插件,其中 eslint-plugin- 前缀可以省略:

1
2
3
4
5
{
"plugins": [
"react"
]
}

接下来开启 ESLint JSX 支持(ESLint 内置选项):

1
2
3
4
5
{
"ecmaFeatures": {
"jsx": true
}
}

然后就可以配置插件提供的规则了:

1
2
3
4
5
6
{
"rules": {
"react/display-name": 1,
"react/jsx-boolean-value": 1
}
}

在webpack中配置eslint-loader

  • 下载npm install eslint-loader -save-dev
  • 指定eslint的配置文件,如果不指定有默认的优先执行顺序
  • 在loader中配置加载器

例如在react项目中配置

  • 通过.eslintignore文件指定不需要走eslint规范的代码

react项目配置参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
{
// 环境定义了预定义的全局变量。
"env": {
"browser": true,
"node": true,
"es6": true,
"mocha": true
},
// JavaScript 语言选项
"parserOptions": {
// ECMAScript 版本
"ecmaVersion": 6,
"sourceType": "module",
// 想使用的额外的语言特性:
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
// "jsx": true,
"arrowFunctions": true,
"classes": true,
"modules": true,
"defaultParams": true
}
},
"plugins": [
"react"
],
"parser": "babel-eslint",
"extends": [
"eslint:recommended"
],
/**
* "off" 或 0 - 关闭规则
* "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出),
* "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
*/
"rules": {
// 禁止条件表达式中出现赋值操作符
"no-cond-assign": 2,
// 允许console语句
"no-console": 0,
// 允许 debugger
"no-debugger": 0,
// 禁止 function 定义中出现重名参数
"no-dupe-args": 2,
// var声明
"no-var": 1,
// 分号;
"semi": [
0,
"always"
],
// 使用 === 替代 == allow-null允许null和undefined==
"eqeqeq": [
2,
"allow-null"
],
// 禁用 alert、confirm 和 prompt
"no-alert": 0,
// 禁用 eval()
"no-eval": 2,
// 禁用 with 语句
"no-with": 2,
// 要求或禁止使用严格模式指令
"strict": 2,
//////////////
// 变量声明 //
//////////////
// 要求或禁止 var 声明中的初始化(初值)
"init-declarations": 2,
// 不允许 catch 子句的参数与外层作用域中的变量同名
"no-catch-shadow": 0,
// 禁止删除变量
"no-delete-var": 2,
// 不允许标签与变量同名
"no-label-var": 2,
// 禁用特定的全局变量
"no-restricted-globals": 0,
// 禁止 var 声明 与外层作用域的变量同名
"no-shadow": 0,
// 禁止覆盖受限制的标识符
"no-shadow-restricted-names": 2,
// 禁用未声明的变量,除非它们在 /*global */ 注释中被提到
"no-undef": 2,
// 禁止将变量初始化为 undefined
"no-undef-init": 2,
// 禁止将 undefined 作为标识符
"no-undefined": 0,
// 禁止出现未使用过的变量
"no-unused-vars": [
0,
{
"vars": "all",
"args": "none"
}
],
// 不允许在变量定义之前使用它们
"no-use-before-define": 0,
// 强制一行的最大长度
"max-len": [
1,
200
],
// 文件末尾强制换行
"eol-last": 0,
// 强制使用一致的反勾号、双引号或单引号
"quotes": [
2,
"single"
],
// 禁止修改 const 声明的变量
"no-const-assign": 2,
// 禁止标识符中有悬空下划线_bar
"no-underscore-dangle": 0,
// 禁用行尾空格
"no-trailing-spaces": 2,
// 禁用不必要的嵌套块
"no-lone-blocks": 2,
// 强制在 JSX 属性中一致地使用双引号或单引号
"jsx-quotes": 0
// "react/display-name": [
// 1,
// {
// "ignoreTranspilerName": false
// }
// ],
// "react/forbid-prop-types": [
// 1,
// {
// "forbid": [
// "any"
// ]
// }
// ],
// "react/no-danger": 1,
// "react/no-did-mount-set-state": 1,
// "react/no-did-update-set-state": 1,
// "react/no-direct-mutation-state": 1,
// "react/no-multi-comp": 1,
// "react/no-set-state": 0,
// "react/no-unknown-property": 1,
// "react/prefer-es6-class": 1,
// "react/prop-types": 1,
// "react/react-in-jsx-scope": 1,
// "react/require-extension": 1,
// "react/self-closing-comp": 1,
// "react/sort-comp": 1,
// "react/wrap-multilines": 1
}
}

结语

我们不应该仅仅是使用 ESLint 这个工具,更应该学习 ESLint 背后的设计理念:不求大而全,但求搭好扎实的
基础架构,提供良好的、可扩展的 API 。小到插件,大到应用程序开发,这一原则都适用。