一文掌握 eslint,再也不怕项目报错
版权声明:本人文章仅在掘金平台发布,请勿抄袭搬运,转载请注明作者及原文链接 🦉
网页版带有主题和代码高亮,阅读体验更佳 🍉
很多初学 vue 的同学一开始如果使用 vue-cli 创建项目并且采用了严格模式的 eslint 的话,肯定深受其扰,各种莫名报错导致项目跑不起来,也不知道那些乱七八糟的配置到底有什么用,一气之下直接删除项目重新搭建,并将这该死的 eslint 列入自己的黑名单。
但是稍微看过一点开源项目的源码,或者你的公司前端技术和氛围很不错的话,可以看到每个工程都有 eslint,虽然它并不能从根源上杜绝屎山代码,但是能帮助开发者减少犯错的可能。作为前端,扪心自问,自己是否具备高级的审美,对代码的排版及格式具备一定的审美能力?写代码时,是否养成了缩进、换行的良好习惯?
来看看没有空格的代码和有空格的代码的区别:
// ===== bad =====
const a=1;
const a===1?true:false
function(a,b){
return a+b
}
arr.filter(item=>item.a===1&&item.b===2)
// ===== good =====
const a = 1;
const a === 1 ? true : false
function(a, b) {
return a + b
}
arr.filter(item => item.a === 1 && item.b === 2)
孰优孰劣,不言而喻。但是每个人的代码风格都是迥异的,只靠标准和规范来推动只是徒劳,统一代码风格这种脏活累活应该交给工具来做。
而 eslint 天生就是做这个的,可以说是团队项目必备工具。如果你在公司项目里写代码时,看到 eslint 报错就束手无策,又或者你想彻底搞清楚 eslint 的配置,比同事稍微多懂一丢丢,那么本篇文章就能满足你。
文章末尾有惊喜~。
搭建 eslint 代码检查环境
如果使用 vscode 那么必须下载 eslint 扩展,使用 webstorm 的话应该内置了。
执行 npm init -y。
执行 npx eslint --init。

它会询问我们期待 eslint 做什么:
- 仅仅检查语法
- 检查语法,发现问题
- 检查语法,发现问题,强制代码风格
一般我会选择第二个。

它会继续询问你,代码使用哪种模块化,这就根据你自己的项目来定了,我们选择第一个。

它继续询问你是否在 vue 或者 react 中使用 eslint,我们选择第三个,你可以根据你的项目来选择。

是否需要 typescript,我们选择需要。

代码运行在浏览器还是 node,我们选择浏览器。

这一步比较关键,它将根据我们之前的选择生成配置文件 eslintrc,这一步就是在选择 eslintrc 文件的后缀,这里我建议选择 json,不建议选择 js 和 yaml。
关于 eslintrc 如何选择文件后缀
我想 yaml 熟悉人的不多,不建议大家选择,如果你选择 js 呢?因为在同一个项目下多个 eslintrc 是依靠后缀来区分优先级的,js > yaml > json。那选择 js 就真的好吗?由于我们的项目可能使用 esmodule 和 commonjs 两种模块化语法,有些时候 .js 、.cjs 的 eslintrc 自身就会报错,初学的同学可能一下就懵了,我是用你来检查错误的,你倒好自己就先报错了。加上后续如果你再使用 typescript 的话,与 tsconfig.json 可能还会继续存在一些冲突,实在没有必要。
为了避免模块化语法带来的各种乱七八糟的问题,我建议你选择 json 作为 eslintrc 的文件后缀,如果没有后缀默认就是 json。我的做法也是不要后缀,默认 json 格式,简洁美观。
eslintrc 初始化配置
初始化生成的配置:
{
"root": true,
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"globals": {
},
"overrides": [
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
}
}
可以看到这个 json 文件是 4 个缩进,我个人喜欢 2 个缩进,但是在 vscode 里没有缩进线:

新增一个 .editorconfig 文件,做如下配置:
# Editor configuration, see http://editorconfig.org
root = true // 是否从根目录起开始生效
[*]
charset = utf-8 // 编码字符集
indent_style = space // 缩进风格 space 或者 tab
indent_size = 2 // 缩进个数
insert_final_newline = true // 末尾插入新行
trim_trailing_whitespace = true // 空格过滤
[*.md]
max_line-length = off
trim_trailing_whitespace = false
该配置文件主要是告诉编辑器,该以怎样的形式表现,例如缩进,编码格式,空格过滤等,在团队协作中也有利于统一代码风格。
配置都比较语义化,就不再赘述了,不懂的可以访问官网 editorconfig。
可以看到缩进线出来了:

eslintrc 配置字段解读
root
该字段表示,你就识别我当前根目录下的 eslint 配置,别再看其他目录下的配置了。这在 menorepo 的项目里比较有用。当 workspace 下有配置,项目目录下又有配置,那么配置可能就会冲突,把范围限定在本项目下就是该字段的意义。
env
该字段表示 eslint 如何看待你的代码,例如 esmodule 下,import,window 之类全局变量和语法不需要声明定义,而 commonjs 下,require,process 不需要声明。来看下效果:

我们在 env 字段下添加 "node": true,报错消失。

其中 "es2021": true 的意思也是一样的,识别 es2021 及之前的新语法,那 2022 后的新特性可能就会报错了。这个看你个人选择,es2021 其实也够用了。
globals
现在,我要在 uniapp 项目里使用 eslint,uni 这个全局变量都不在 broswer、es2021、node 里,那 eslint 就会报错找不到这个变量,这时候在 globals 里定义 uni 为全局变量,就不会报错了。


extends
这个字段可以理解为继承、扩展。有些时候 eslint 的内置规则我们会觉得不够用,又或者社区有更好的规则,再或者我们自己有自己定义的规则集,这时候就需要用到这个字段了,他表示我们需要继承扩展的规则集。例如现在社区最流行的是 airbnb 规则集,那么我们就可以:"extends": "eslint-config-airbnb"。当然了,可以扩展多个:
...
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"eslint-config-airbnb"
],
...
不过规则集之间可能会各有冲突,使用时还需要注意。
最关键的是,我们看似仅仅只是扩展了规则集,实际上:
extends会继承别人写好的一份.eslintrc的配置,这份配置不仅仅包括了rules还有parser,plugins之类的东西。 (海怪)
规则集的命名规则一般是:eslint-config-xxxx,所以后续看到此类包就知道是 eslint 规则集了。
overrides
如果你想对某些特殊的文件指定解析器,那么可能会用到此字段。使用示例:
...
"overrides": [
{
"files": ["*.md"],
"processor": "a-plugin/markdown"
},
// 下面的配置就是小型的 eslintrc,parser、parserOptions 之类的字段也可以继续配置
{
"files": ["**/*.{js,jsx}"], // 只处理 js 和 jsx 文件
"parser": "@babel/eslint-parser", // 使用 babel 来解析 js 文件
"parserOptions": {
"sourceType": "module", // 支持 import/export
"allowImportExportEverywhere": false,
"ecmaFeatures": {
"globalReturn": false,
},
},
},
]
...
但你基本上用不到这个字段,了解即可。
parser
这个选项指定解析器,例如,eslint 是用来检查 js 语法的,但是 ts 它不支持,这时候需要使用 ts 提供的解析器来进行解析。
...
"parser": "@typescript-eslint/parser",
...
...
"parser": "vue-eslint-parser",
...
这些 parser 都是独立的 npm 包,需要下载使用。针对不同的主语言环境使用不同的解析器。
parserOptions
这里我们直接看官网的解释好了:

plugins
plugins 可以理解规则扩展,例如针对 vue、react 等前端框架,他们有自己的文件后缀,还有自己的语法规则,这些语法校验都需要社区来提供。此时 eslint 自己提供的规则就不够用了,所以需要插件来扩展校验规则。
插件的命名规则一般是:eslint-plugin-xxxx,所以后续看到此类包就知道是 eslint 插件了。
例如,vue 语法检查需要下载 eslint-plugin-vue,react 语法检查需要下载 eslint-plugin-react。一般来说,parser 和 plugins 是成对使用的,请记住这点,很重要。
例如,支持 vue 语法检查:
"parser": "vue-eslint-parser",
"plugins": ["eslint-plugin-vue"]
支持 typescript 语法检查:
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint/eslint-plugin"]
rules
这个就是自己自定义的规则,没啥特别的。例如我们设置没有分号报错:

报错级别有三种:error,warn,off,分别对应数字 2,1,0。还有一些写法,感兴趣的可以自行研究:
"react/jsx-filename-extension": [
1,
{
"extensions": [
".js",
".jsx"
]
}
],
parser、extends、plugins 的区别
可能看到这里有些朋友已经懵了,那这三者有啥区别?
parser 是让 eslint 能认识语法。
plugins 是提供特殊语法的检查规则集。
extends 说白了就是 parser 和 plugins 配置的简写(可以简单这么理解,但不全对),我们前面说过 plugins 和 parser 是成对出现的。
而 extends 的作用就在于只要我声明了继承的规则集,即使我没有配置 parser 和 plugins,我扩展的语法规则集也能生效。
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
来看示例,我们把 plugins 和 parser 删除,错误提示依旧生效。

.eslintignore
有些时候,我们并不希望 eslint 对某些文件做代码检查,例如我们 build 产物,这时候要将这些产物代码检查进行忽略。在项目根目录下新建一个 .eslintignore 文件,如果你懂配置 .gitignore,那么语法都是一样的,类似于正则匹配,来看示例:
node_modules/*
test/*
dist/*
build/*
开头是文件目录名,* 表示目录下所有文件都进行忽略。配置后这些文件下的代码都将不再进行代码检查。
写在最后
恭喜你看到最后,相信你已经掌握 eslint,再也不怕代码报错了。答应给大家的惊喜:
推荐大家去看海怪的Linter上手完全指南,这本电子书从各种 lint 的发展由浅入深地带领大家学习 lint 工具,帮助你理清各个 linter 之间的发展关系,从此离前端工程化更进一步。
往期推荐
开发一个 npm 库应该做哪些工程配置? 40+ 👍🏻 50+ 💚
分享我在前端学习与开发中用到的神仙网站和工具 40+ 👍🏻 110+ 💚
uniapp 踩坑记录(二) 130+ 👍🏻 150+ 💚
闲来无事,摸鱼时让 chatgpt 帮忙,写了一个 console 样式增强库并发布 npm 100+ 👍🏻 110+ 💚
uniapp 初体验踩坑记录 30+ 👍🏻 60+ 💚
两小时学会 JS 正则表达式,终身不忘 50+ 👍🏻
【一年前端必知必会】如何写出简洁清晰的代码 50+ 👍🏻
【一年前端必知必会】了解 Blob,ArrayBuffer,Base64 40+ 👍🏻 90+ 💚
转载自:https://juejin.cn/post/7254476003065020473