跳到主要内容

彻底搞懂 ESLint 与 Prettier 之间的关系

· 阅读需 12 分钟

ESLint 是一个 javascript 代码检测工具,例如未使用的变量,未定义的引用,比较时使用三等,禁止不必要的括号 等等代码质量检测, 其出现大大提高了团队协作的代码规范统一性,以及个人的代码质量,深受 web 开发者们的青睐。但是其众多的配置参数,语法规则,也同样让人迷糊。好在各大 web 框架的脚手架中都内置了 ESLint 插件,渐渐的像 ESLint 看齐,开发者们无需再过多手动配置,即可享受 ESLint 带来的团队及个人效益。但是考虑到并不是所有的框架都内置了并且有许多像我一样爱折腾的朋友们,我们还是需要对其一探究竟。

话不多说,我们直接上代码。

NPM ESLint 命令行

mkdir eslint-app && cd eslint-app                // 创建空目录并进入目录
npm init // 初始化 npm
touch index.js // 创建入口文件
npm i eslint -D // 安装 eslint 依赖

我们创建了一个新的目录,并且安装了好了 ESLint ,接着我们在 index.js 中写入代码

const hello = 'hello';

package.jsonscripts 选项中加入一条检测脚本,代表我们要对 目录下所有的 js 文件进行 ESLint 检测

"scripts": {
"lint": "eslint ."
}

紧接着执行 npm run lint,不出意外的话,应该会出现一个报错,提示我们需要一个 ESLint 配置文件

因此,我们先在根目录下手动创建一个 eslint 配置文件,命名可以是 .eslintrc.json,eslintrc.js.eslintrc.yaml,甚至配置在 package.json 中,我这里使用了 .eslintrc.json,并添加了以下配置代码

{
"env": { // 全局环境变量
"browser": true, // 浏览器环境
},
"extends": "eslint:recommended", // 继承 eslint 默认配置
"parserOptions": { // 指定 javaScript 语言类型和风格
"sourceType": "module" // 导入方式设定为模块导入
},
"rules": { // 配置规则
"no-unused-vars": 1// 警告不允许出现未使用的变量
"semi": [1, "always"]// 警告强制加上句尾分号
}
}

.eslintrc即将废弃,可以使用 .eslintrc.json 完全代替

配置文件已经创建好了,我们继续执行之前的 npm run lint,如果你的 index.js 代码和我上述一样,此时终端应该出现了警告,告诉我们 index.js 定义了 hello 变量但没有使用。至此我们第一步的校验已经大功告成

许多朋友已经养成了不写分号的习惯但团队又必须要求加上句尾分号,这个时候可以用到 ESLint 自带的格式化功能,他能对我们一些比较基本的语法问题进行自动格式化,在 package.json scripts 中添加一条格式化脚本,可以看到与 lint 的区别就是加了一个 --fix 参数

"scripts": {
"format": "eslint . --fix"
},

紧接着我们去掉 index.js 第一行的分号,执行 npm run format,然后回头看 index.js, 应该发现句尾已经自动帮我们加上了分号了

eslint-webpack-plugin(eslint-loader)

自从 webpack 5 开始,eslint-loader 已经不再被 webpack 推荐,具体原因见 https://github.com/webpack-contrib/eslint-webpack-plugin#about-plugin

那么问题来了,ESLint 如何与现有项目进行融合?以及在实际项目中,每次如果需要手动执行一次 lint 才能看到我们的语法错误,那岂不是是十分麻烦的?

这个时候 eslint-webpack-plugin 派上用场了,eslint-webpack-pluginwebpack 插件,在项目编译期间,能对我们的 js 代码进行实时的检测。我们先手动搭建一个 webpack 环境,在此项目上继续安装依赖

npm i webpack-cli webpack webpack-dev-server webpack-html-plugin eslint-webpack-plugin -D

package.json scripts 中添加一条启动脚本

"scripts": {
"start": "webpack serve"
}

并在根目录添加 webpack.config.js 配置文件

const HtmlWebpackPlugin = require('html-webpack-plugin');
const EslintWebpackPlugin = require('eslint-webpack-plugin');

module.exports = {
mode: 'development',
entry: './index.js',
devtool: 'inline-cheap-module-source-map',
plugins: [new HtmlWebpackPlugin(), new EslintWebpackPlugin()],
devServer: {
port: 9000,
},
};
  • 手动修改 index.js 去掉句尾分号,随即运行 npm start,观察控制台会发现出现了警告,并打开浏览器输入网址 http://localhost:9000/,按下 F12,浏览器的控制台中同样出现了警

  • 手动修改 index.js 加上句尾分号,随即运行 npm start,观察控制台会发现警告消失了,并观察浏览器的控制台中的警告也消失了

如果同样想支持保存即自动格式化,只需在 webpack 配置文件的 EslintWebpackPlugin,中传入 { fix: true } 选项就可以了

NPM 插件 Perttier

Prettier 又是什么?和 ESLint 又有什么关系?

上述说到 ESLint 的作用是代码质量检测,Prettier 的作用则主要是代码格式化,那不是和 ESLint 冲突了吗?并不是,ESLint 只能格式化 js/ts 文件,而 Prettier 支持多种文件

  • JavaScript/TypeScript
  • CSS/Less/SCSS
  • HTML
  • JSON/YAML/GraphQL
  • Markdown
  • Vue/React/Angular

Prettier 自身的规范更倾向于个人/团队的代码风格的规范或统一,例如每行最大长度,单引号还是双引号,等号左右空格,使用 tab 还是 空格等等,将他与 ESLint 一起协同工作犹如如虎添翼

NPM 插件 eslint-plugin-prettier

eslint-plugin-prettier 是 一个 ESLint 插件, 由 Prettier 生态提供,用于报告错误给 ESLint

npm i prettier eslint-plugin-prettier eslint-config-prettier

eslint-config-prettier 的作用是使用 Prettier 默认推荐配置,并且关闭 eslint 自身的格式化功能,防止 PrettierESLint 的自动格式化的冲突

在项目根目录下添加 Prettier 配置文件 .prettierrc

{
"singleQuote": true, // 强制单引号
"semi": true // 强制句尾分号
}

修改 index.js

const hello = 'hello';
console.log(hello);

修改 .eslintrc.json

{
"env": {
"browser": true
},
"extends":["plugin:prettier/recommended"], // 使用 prettier 推荐配置
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
}
}

重新执行 npm start

  • 如果配置了 EslintWebpackPluginfix: true 选项,会发现双引号已变成单引号,并且自动加上了分号
  • 反之,则出现 eslint prettier 报错,错误的使用了双引号,并且未加句尾分号

ESlintPrettier 的合作关系: 由于 ESlint 自身自动格式化功能不够完善,Prettier 代替了 ESlint 格式化能力,利用了 ESlint 的检测和提示

VS Code ESLint/Prettier 插件

似乎还漏了什么,上面的代码的提示都是在项目编译时提示,好不容易写了一大串代码,运行时发现了 n 个语法警告和报错,顿时心态炸裂

VS Code ESLint 插件

回到 VS Code,按下 ctrl + shift + X(mac: command + shift + X),进入插件商店,安装 ESLint 插件,恢复 index.js 代码至以下

const hello = 'hello';

console.log(hello);

喜出望外,编辑器未雨绸缪的提示了报错与警告,不必再等到编译时提示了,在写代码的时候我们就可以发现错误了,这就是 VS Code ESLint 插件的能力。

VS Code ESLint 插件运行需要本地项目的 ESLint 相关插件和配置都存在(依赖,配置文件),但不一定要被编译。比如在 webpack 中可以不使用 eslint-loader 或者 eslint-webpack-plugin

VS Code Prettier 插件

在项目比较大文件比较多的时候,依赖 NPM Prettier 的自动格式化可能会导致保存后需要很久才能完成,因为它需要先编译一遍 javascript,这个时候 VS CodePrettier 插件的作用就体现出来了,使用上述中同样方法在插件商店安装 Prettier 插件

在项目的根目录下创建 .vscode 目录,进入目录创建 .settings.json 文件,添加以下代码

{
"editor.defaultFormatter": "esbenp.prettier-vscode", // 默认使用 prettier 作为格式化工具
"editor.formatOnSave": true // 保存代码时格式化
}

再次回到 index.js,保存,会发现代码已经被自动格式化了。此时修改 package.josnscripts 的 格式化 脚本为

"format": "prettier --write ."

每次执行 npm format 命令后将会对项目中所有 Prettier 支持的格式的文件进行格式化(包括但不限于 JSTS),常常被用于 git hook 的提交前检测和格式化

到了这个时候, 其实 VS Code 的 格式化已经和 NPM 的格式化冲突了,所以可以完全删除 eslint-webpack-plugin 插件了,解决冲突的同时,也大大的提高了代码的编译效率,,将检测与格式化的工作完全交给编辑器来做。这同样也是目前各大框架流行的做法,否则 webpack 中的 ESLint 也要完整解析一次代码,在项目比较大的时候特别影响编译速度,以及控制台带来的一连串警告和报错影响开发者的体验

总结

  1. NPM ESLint 代码编译时时的语法检测
  2. NPM Prettier 代码编译时的自动格式化
  3. VS Code ESLint 编辑器对开发时的代码进行即时的语法检测和提示
  4. VS Code Prettier 编辑器对对开发时的代码进行即时的格式化

:::