一、什么是ESlint、有什么特性
描述:
ESLint
是一个集代码审查和修复
的工具,它的核心功能是通过配置一个个规则来限制代码的合法性和风格
特性:
1. 发现问题: ESLint静态分析代码以快速发现问题。ESLint内置于大多数文本编辑器中,您可以将ESLint作为持续集成管道的一部分运行
2. 自动修复: ESLint发现的许多问题可以自动修复。ESLint修复程序具有语法意识,因此您不会遇到传统查找和替换算法引入的错误
3. 定制: 预处理代码,使用自定义解析器
,并编写与ESLint内置规则一起使用的自己的规则。您可以自定义ESLint,使其完全按照项目所需的方式工作
二、ESlint使用及配置
基本使用:
安装
npm install eslint --save-dev
初始化配置文件,根目录生成.eslintrc.js
npx eslint --init
两种配置方式:
- 配置注释:使用JavaScript注释把配置信息直接嵌入到一个代码源文件中
- 配置文件:1. 使用 JavaScript、JSON 或者 YAML 文件为整个目录(处理你的主目录)和它的子目录指定配置信息。可以配置一个独立的
.eslintrc.*
文件,或者直接在package.json
文件里的eslintConfig
字段指定配置,ESLint 会查找和自动读取它们,再者,你可以在命令行运行时指定一个任意的配置文件。
具体配置字段:
1. parser解析器及解析参数
解析器
将源代码转换为称为抽象语法树(AST)
的数据格式,然后,插件使用这种数据格式围绕代码的外观或行为创建称为lint规则的断言。
ESLint附带了一个内置的解析器(称为espree)
,因此如果你只编写标准JavaScript,就不需要自定义解析器了
如果我们想支持非标准JavaScript语法,我们需要做的就是为ESLint提供一个可供使用的替代解析器
。根据工程的实际情况,对解析器进行设置,比如基于vue框架
的工程需要用到能解析vue语法解析器;再比如使用到TypeScript
的工程,需要配置能解析TypeScript的解析器
这里可以类比webpack,自身只能处理js、及json文件,css、html等文件需要通过自定义loader处理来理解
常用解析器:
- @babel/eslint-parser:一个对Babel解析器的包装,使其能够与 ESLint 兼容
- @typescript-eslint/parser:
TSLint
被弃用后,将TypeScript转换成与estree兼容的形式,以便在ESLint中使用
解析参数parserOption:
{
// 解析器,默认espree
parser: "espree",
parserOption: {
// 指定要使用的ECMAScript版本,默认值5,可以使用 6、7、8、9 或 10 来指定你想要使用的 ECMAScript 版本。你也可以用使用年份命名的版本号指定为 2015(同 6),2016(同 7),或 2017(同 8)或 2018(同 9)或 2019 (same as 10)
ecmaVersion: 5,
// 设置为 "script" (默认) 或 "module"(如果你的代码是 ECMAScript 模块)
sourceType: "module",
// 这是个对象,表示你想使用的额外的语言特性,所有选项默认都是 false
ecmafeatures: {
// 是否允许在全局作用域下使用 return 语句
globalReturn: false,
// 是否启用全局 strict 模式(严格模式)
impliedStrict: false,
// 是否启用JSX,支持 JSX 语法并不等同于支持 React。React 对 ESLint 无法识别的JSX语法应用特定的语义。如果你正在使用 React 并且想要 React 语义支持,我们建议你使用 [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react)。
jsx: false,
// 是否启用对实验性的objectRest/spreadProperties的支持
experimentalObjectRestSpread: false
}
},
}
2. env环境
一个环境定义了一组预定义的全局变量
指定不同的环境可以给对应环境下提供预设的全局变量,比如说在 browser 环境下,可以使用 window 全局变量;在 node 环境下,可以使用 process 全局变量等。 可用的环境包括: 可选配置项如下:
browser
- 浏览器环境中的全局变量。node
- Node.js 全局变量和 Node.js 作用域。commonjs
- CommonJS 全局变量和 CommonJS 作用域 (用于 Browserify/WebPack 打包的只在浏览器中运行的代码)。shared-node-browser
- Node.js 和 Browser 通用全局变量。es6
- 启用除了 modules 以外的所有 ECMAScript 6 特性(该选项会自动设置ecmaVersion
解析器选项为 6)。- 更多可见官网
这些环境并不是互斥的,所以可以同时定义多个。可以在源文件里、在配置文件中或使用 命令行 的
--env
选项来指定环境。
3. globals全局变量
脚本在执行期间访问的额外的全局变量
当访问当前源文件内未定义的变量时,no-undef 规则将发出警告。如果你想在一个源文件里使用全局变量,在Globals中定义这些全局变量,这样ESLint就不会发出警告了
"globals": {
"var1": "writable", // "off" 禁用全局变量
"var2": "readonly"
}
4. rules规则
启用的规则及其各自的错误级别,配置文件
ESLint 附带有大量的规则,要改变一个规则设置,你必须将规则ID
设置为下列值之一:
"off"
或0
- 关闭规则"warn"
或1
- 开启规则,使用警告级别的错误:warn
(不会导致程序退出)"error"
或2
- 开启规则,使用错误级别的错误:error
(当被触发的时候,程序会退出)
"rules": {
"eqeqeq": "off", // 要求使用 `===` 和 `!==`
"curly": "error", // 强制所有控制语句使用一致的括号风格
"quotes": ["error", "double"] // 引号
}
5. extends配置扩展
实际项目中配置rules
的时候,不可能团队一条一条的去商议配置,太费精力了。通常的做法是使用业内大家普通使用的、遵循的编码规范;然后通过extends
去引入这些规范。extends
配置的时候接受字符串
或者数组
:
- 指定配置的字符串(配置文件的
路径
、可共享配置的名称、eslint:recommended
或eslint:all
) - 字符串数组:每个配置继承它前面的配置
extends可以理解为rules的快捷配置字段,一般先配置extends为业内通用规范,且数组时后面的会覆盖前面的,并自定义配置rules覆盖extends中不满足你想要规范的规则
{
"extends": [
"eslint:recommended",
"plugin:vue/essential", // 实际npm包插件eslint-config-vue/essential [插件名:配置名]
"airbnb-base", // 实际npm包插件eslint-config-vue/airbnb-base
"@vue/prettier",
"./node_modules/coding-standard/.eslintrc-es6"
]
}
从上面的配置,可以知道extends支持的配置类型可以是以下几种
eslint
开头的:是ESLint官方的扩展;常见配置eslint:recommended
、eslint:all
plugin
开头的:是插件类型扩展,可以省略包名的前缀eslint-plugin-
,比如plugin:vue/essential
,实际上使用的是eslint-config-vue
插件,而essential
是配置名,可见插件配置说明,如下图,包eslint-config-vue中定义了配置参数essential
eslint-config
开头的:来自npm
包,使用时可以省略前缀eslint-config-
,比如上面的直接写成airbnb-base
;@
开头的:扩展和eslint-config
一样,只是在npm
包上面加了一层作用域scope
;- 一个执行配置文件的相对路径或绝对路径;
常用extends配置:
eslint:recommended
:ESLint内置的推荐规则,属性启用一系列核心规则,这些规则报告一些常见问题,在 规则页面 中被标记为✅eslint:all
:ESLint内置的所有规则;eslint-config-airbnb-base
:airbnb的JS规范;eslint-config-standard
:standard的JS 规范;
6. plugins插件
ESLint
虽然可以定义很多的rules
,以及通过extends
来引入更多的规则,但是说到底只是检查JS语法。如果需要检查Vue
中的template
或者React
中的jsx
,就束手无策了。所以引入插件的目的就是为了增强ESLint
的检查能力和范围。
在配置文件里配置插件时,可以使用
plugins
关键字来存放插件名字的列表。插件名称可以省略eslint-plugin-
前缀。
{
"plugins": [
"vue", // 等价于"eslint-plugin-vue"
"@typescript-eslint" // 等价于@typescript-eslint/eslint-plugin
]
}
7. 其他配置
配置当前目录为 root
ESLint检测配置文件步骤:
- 在要检测的文件同一目录里寻找
.eslintrc.*
和package.json
; - 紧接着在父级目录里寻找,一直到文件系统的根目录;
- 如果在前两步发现有
root:true
的配置,停止在父级目录中寻找.eslintrc
; - 如果以上步骤都没有找到,则回退到用户主目录
~/.eslintrc
中自定义的默认配置;
通常我们都习惯把 ESLint 配置文件放到项目根目录,因此可以为了避免 ESLint 校验的时候往父级目录查找配置文件,所以需要在配置文件中加上 root: true。
{
"root": true,
}
三、ESlint校验
第二块配置完了配置文件,但是怎么校验文件呢
校验.js类型文件
// 校验 a.js 和 b.js
npx eslint a.js b.js
// 校验 src 和 scripts 目录
npx eslint src scripts
校验其他类型文件
通常ESLint
只能校验JS
文件。比如需要校验.vue
文件,光配置vue插件
和vue-eslint-parser解析器
是不够的,还需要让ESLint
在查找文件的时候找到.vue
文件。ESLint
提供了--ext
来指定具体需要校验的文件
npx eslint --ext .js,.vue src
自动修复部分校验错误的代码
rules列表项 中标识了🔧规则表示该规则是可以自动修复的,ESLint
提供了--fix
package.json配置scripts
{
"scripts": {
"lint": "npx eslint --ext .js,.vue src",
"lint:fix": "npx eslint --fix --ext .js,.vue src",
}
}
过滤一些不需要校验的文件
对于一些公共的JS、测试脚本或者是特定目录下的文件习惯上是不需要校验的,因此可以在项目根目录通过创建一个.eslintignore
文件来配置,告诉ESLint
校验的时候忽略它们:
public/
src/main.js
四、为什么要用ESLint
1、背景:
总结为两点:
-
保持代码风格一致
:一千个程序员,就有一千种代码风格。在前端开发中,有几个至今还在争论的代码风格差异。如果一个工程代码风格不一样,可以想象随着项目迭代扩大,简直不忍直视- 单引号还是双引号?
- 代码行结束是否需要分号?
- 两个空格还是四个空格?
-
减少代码出错几率
:由于JavaScript 的灵活性,往往一段代码能有多种写法,这时候也会导致协同时差异。并且,有一些写法可能会导致不易发现的 bug,或者这些写法的性能不好,开发时也应该避免
为了解决这类静态代码问题,每个团队都需要一个统一的JavaScript
代码规范,团队成员都遵守这份代码规范来编写代码。当然,靠人来保障代码规范是不可靠的,需要有对应的工具来保障,ESLint
就是这个工具
2、为什么不是Prettier
有的读者看到这里,可能会说:Prettier
也可以保证代码风格一致。是的Prettier
确实可以按照设置的规则对代码进行统一格式化,但是需要明确的一点是,Prettier
只会在格式上对代码进行格式化,一些隐藏的代码质量问题
Prettier是无法发现的,而ESLint
可以。
3、目标
开发时提示,保存时自动修复,提交时检测
五、项目实践
1、vue-cli创建工程
// package.json
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential", // 等价于用到eslint-plugin-eslint/essential
"eslint:recommended",
],
"parserOptions": {
"parser": "babel-eslint" // 解析器
},
"rules": {}
},
2、在VSCode中支持ESLint
前面做的配置,都需要执行命令才能进行检查和修复代码,还是挺不方便的,如果我希望编辑完
或者保存时
去检查代码该如何做呢?可以直接在IDE
里安装ESLint插件
- 在 VSCode 左下角找到一个齿轮 ⚙ 图标,点击后选择设置选项,这个时候打开了设置面板;
- 然后在 VSCode 右上角找到打开设置(json)的图标,点击后,会打开 settings.json 文件;
- 然后把以下配置贴进去即可;
{
"eslint.alwaysShowStatus": true, // 总是在 VSCode 显示 ESLint 的状态
"eslint.quiet": true, // 忽略 warning 的错误
"editor.codeActionsOnSave": { // 保存时使用 ESLint 修复可修复错误
"source.fixAll": true,
"source.fixAll.eslint": true
}
}
3、pre-commit
两个背景
- 以上只是通过
ESLint
自动修复能够修复的错误以代码的格式化,但是在实际开发的时候难免会遇到无法fix的错误
,可能开发人员也忘记修改,如果这个时候把代码提交到远程仓库,那就把糟糕的代码给提交上去了 - 使用命令修复的时候,不小心修改了他人代码,很容易造成冲突。如果一个项目以前没有用过 linter,如何最方便地开始使用并且尽量不改动之前的代码?
解决以上问题的一个方案就是,在提交代码的时候,自动修复格式问题,并且只修复自己改动的代码
可以通过配置git hooks
的pre-commit
钩子来实现这个目的。主要是利用了husky
和lint-staged
这 2 个包。
- husky:用来配置 git hooks
- lint-staged:拿到
staged
文件进行处理
"lint-staged": {
"**/*.{js,vue}": [
"eslint --fix",
"git add"
],
"**/*.{less,css,vue}": [
"stylelint --config ./.stylelintrc --fix",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}