Skip to content

ESLint 与 Prettier

ESLint: 是针对 EScript 的一款代码检测工具,它可以检测项目中错误格式和代码中的错误。如果写出不符合规范的代码会被警告,ESLint其本身也包含代码格式化功能,但在某些情况下并不能正确格式化。

Prettier: 是一款强大的代码格式化工具,支持 JavaScript、TypeScript、CSS、SCSS、Less、JSX、Angular、Vue、GraphQL、JSON、Markdown 等语言,基本上前端能用到的文件格式它都可以搞定,是当下最流行的代码格式化工具。

一、ESLint 入门

环境 env

ESLint 默认不开启任何环境,可以在env字段下使用"env_name":true的方式开启,环境之间不会互斥,可以同时开启多个环境,如:

js
module.exports = {
    "env": {
        "browser": true,
        "node":true,
        "es6":true
    }
}

开启环境后,ESLint 能正常解析代码中的全局变量,可能还会开启对应的语法解析选项。

rules

rules 主要是配置 eslint 的校验规则,例如代码缩进方式是空格还是 tab

js
module.exports = {
    'rules': {
		'indent': ['error','tab']
    }
}

配置书写方式为:

  • "off" 或 0 - 关闭规则
  • "warn" 或 1 - 启用并视作警告(不影响退出)
  • "error" 或 2 - 启用并视作错误(触发时退出代码为 1)

全局变量 globals

env 可以方便地支持特定环境下的全局变量,但 JavaScript 的执行环境要复杂得多,每个模块和外部依赖都有可能注入自己的全局变量,为了避免这被识别成错误,需要在配置中指出代码中用到的外部全局变量。

例如在 uniapp 开发小程序中:

js
module.exports = {
	'globals': {
		'wx': 'readonly',
		'uni': 'readonly',
		'getCurrentPages': 'readonly',
		'getApp': 'readonly'
	}
}

其中 uni wx 等这些全局 api 实在特定环境下才存在的。

解析选项 parserOptions

在 ESLint 解析的时候提供一些语言特性的支持,如 ES 语法、JSX。ESLint 默认支持 ES5 语法。

配置语法语法如下:

js
module.exports = {
    "parserOptions":{

        /* ecmaVersion: 指定 ECMA 语法版本
        *  取值:
        *      - "latest": 使用最新版本,现在 (2021) 等同于 12
        *      - 版本号:3, 5(默认), 6, 7, 8, 9, 10, 11, 12
        *      - 年份命名法:2015(=6), 2016(=7), 2017(8) ...
        */ 
        "ecmaVersion":  "latest",

        /* sourceType: 脚本类型,普通脚本 或 ES 模块脚本
        *  取值:"script"(默认) | "module"(ES 模块脚本)
        */
        "sourceType":"module",

        /* ecmaFeatures: 支持的特性语法*/
        "ecmaFeatures": {
        
            // 支持在全局使用 return 
            "globalReturn": true,

            // 默认使用严格模式(ES 5 或 以上)
            "impliedStrict": true,

            // 支持 JSX 语法
            "jsx": true 
        }
    }
}

需要注意的是,开启更高的 ES 解析选项并不会自动支持对应的 ES 全局变量。所以,为了支持最新的 ES 语法:

js
{
  "env":{
    // 支持 es 语法全局变量识别,这是必须的
    "es2021": true,
  },
  /* 下面是可选的,因为 es2021 会自动设置 "ecmaVersion": 12
  "parserOptions": {
    "ecmaVersion": 12
  }
  */
}

使用其他解析器 parser

ESLint 默认使用的是 Espree 解析器。你也可以通过parser字段使用其他解析器。 解析器需要满足两个条件:

  • 必须是一个 Node 模块,并且在配置文件所在目录下能找到。比如同目录下的 npm 包,一个由路径指定的 js 文件。
  • 满足 ESLint 解析器接口。

如果项目中用到一些语言增强工具(TypeScript、Babel)或者框架(React、Vue),就需要使用与之对应的解析器。 以 TypeScript 为例,为了正确解析代码,你需要:

  1. 在.eslintrc.json对应的目录下安装解析器
npm install --save-dev @typescript-eslint/parser
  1. 在配置文件中配置
js
module.exports = {
    {
    "parser": "@typescript-eslint/parser"
    }
}

使用插件 plugins

ESLint 支持第三方插件的使用,使用前,需要先在配置文件的目录上安装对应的 npm 包。

安装插件之后,就可以在 ESLint 的plugins数组中添加该配置文件需要使用的插件。不过,插件的各项规则配置都是默认关闭的,所以plugins只是使用插件功能的前提,你必须在 rules, extends, env 中开启你需要的规则特性。

js
module.exports = {
  "plugins":["jest"],
  "extends": ["plugin:jest/recommended"],
  "env":{
    "jest/global":true
  },
  "rules":{
    "jest/valid-expect": "error"
  }
}

继承配置 extends

使用extends能很方便地继承已有配置的全部特性,包括rules, env, extends等。

配置继承与面向对象中“类的继承”类似。如果称被继承配置为“父配置”,继承配置为“子配置”,那么子配置具有父配置的所有特性,并且可以在子配置中的规则会覆盖父配置的同一规则。配置继承也具有传递性。

配置的继承极大方便了项目之间通用配置的共享,也避免了每次繁琐的大量规则配置。

extends数组包含了配置中继承的所有父配置,当只有一个父配置时,也可以使用{"extend": "config-name"}的形式。 父配置可以通过几种方式指定:

  • ESLint 内置配置 "eslint:recommended" 和 "eslint:all"。
  • 共享配置的包名称 "eslint-config-<config-name>", 命名及其缩写和插件命名类似。如
js
module.exports = {
  "extends": ["standard"] // 同 eslint-config-standard
}
  • 插件内导出的配置 "plugin:a-plugin/config", plugin:前缀为了区分简写下的配置和插件包名。如
js
module.exports = {
  // 别忘了 plugins
  "plugins": ["react"],
  "extends": ["plugin:react/recommended"]
}
  • ESLint 配置的文件路径。如 {"extends": "./.my-eslintrc.json"}。

二、ESLint 安装使用

1. 安装 ESLint

pnpm install -D eslint  // ESLint 本体

2. 初始化 ESLint 配置

npx eslint --init

当然,你也可以直接复制一份 eslintrc.js 文件,而不走初始化指令流程

3. 配置初始化选择

? How would you like to use ESLint? ... 
  To check syntax only
  To check syntax and find problems
> To check syntax, find problems, and enforce code style
---------------------------------------------------------------- 选择强制代码风格
√ How would you like to use ESLint? · style       
? What type of modules does your project use? ... 
> JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these
---------------------------------------------------------------- 选择ESM规范
√ How would you like to use ESLint? · style       
√ What type of modules does your project use? · esm
? Which framework does your project use? ... 
  React
> Vue.js
  None of these
---------------------------------------------------------------- 选择VUE框架
√ How would you like to use ESLint? · style       
√ What type of modules does your project use? · esm
√ Which framework does your project use? · vue
? Does your project use TypeScript? » No / Yes
---------------------------------------------------------------- 使用TS yes
√ How would you like to use ESLint? · style       
√ What type of modules does your project use? · esm
√ Which framework does your project use? · vue
√ Does your project use TypeScript? · No / Yes
? Where does your code run? ...  (Press <space> to select, <a> to toggle all, <i> to invert selection)
√ Browser
√ Node
---------------------------------------------------------------- 空格增选Node 回车
√ How would you like to use ESLint? · style       
√ What type of modules does your project use? · esm
√ Which framework does your project use? · vue
√ Does your project use TypeScript? · No / Yes
√ Where does your code run? · browser, node
? How would you like to define a style for your project? ... 
  Use a popular style guide
> Answer questions about your style
---------------------------------------------------------------- 用过A&Q来配置规则
√ How would you like to define a style for your project? · prompt
? What format do you want your config file to be in? ...
> JavaScript
  YAML
  JSON
---------------------------------------------------------------- 配置文件使用js文件
这里直接回车,因为这些格式化配置最后都要删掉,采用prettier规定格式
----------------------------------------------------------------
√ What style of indentation do you use? · tab
√ What quotes do you use for strings? · double
√ What line endings do you use? · unix
√ Do you require semicolons? · No / Yes
The config that you‘ve selected requires the following dependencies:
eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
? Would you like to install them now? » No / Yes
---------------------------------------------------------------- 选择yes现在立即初始化配置文件
√ Would you like to install them now? · No / Yes
? Which package manager do you want to use? ...
> npm
  yarn
  pnpm
---------------------------------------------------------------- 包管理器选择npm

4. 安装完成后(根目录会生成.eslintrc.js文件)

这个配置文件是默认生成的,还不能用于项目后面会修改此配置文件。

js
module.exports = {
	"env": {
		"browser": true,
		"es2021": true,
		"node": true
	},
	"extends": [
		"eslint:recommended",
		"plugin:vue/essential",
		"plugin:@typescript-eslint/recommended"
	],
	"parserOptions": {
		"ecmaVersion": "latest",
		"parser": "@typescript-eslint/parser",
		"sourceType": "module"
	},
	"plugins": [
		"vue",
		"@typescript-eslint"
	],
	"rules": {
		"indent": [
			"error",
			"tab"
		],
		"linebreak-style": [
			"error",
			"unix"
		],
		"quotes": [
			"error",
			"double"
		],
		"semi": [
			"error",
			"always"
		]
	}
};

5. VsCode 安装 ESLint 插件

在商店中查找ESLint插件,然后安装它,不需要配置,在项目内如果集成了eslint的npm包,这个插件会根据配置文件,对代码检查问题进行高亮提示。

6. Eslint 结合构建工具

以上方式配置好后足以在编码时拥有 Eslint 提示和格式化代码了。但是如果想在运行项目时在 cmd 上有提示,就需要配合构建工具提供的相关插件了。

Vite

安装 vite-plugin-eslint(eslint 结合 vite 使用)

pnpm install -D vite-plugin-eslint

配置vite.config.ts

js
import eslintPlugin from 'vite-plugin-eslint';

export default defineConfig({
    plugins: [
        vue(),
        eslintPlugin({
            include: ['src/**/*.ts', 'src/**/*.vue', 'src/*.ts', 'src/*.vue'],
        }),
    ]
});

Webpack

安装 eslint-webpack-plugin(eslint 结合 webpack 使用)

pnpm install -D webpack webpack-cli

配置 webapck.config.js

js
// webpack.config.js
const ESLintPlugin = require('eslint-webpack-plugin')

module.exports = {
    // 添加 eslint-webpack-plugin 插件实例
    plugins: [new ESLintPlugin()]
}

三、Prettier 安装使用

  1. 安装prettier
pnpm install -D prettier # prettier本体
pnpm install -D eslint-config-prettier #eslint兼容的插件
pnpm install -D eslint-plugin-prettier #eslint的prettier
  1. 配置 .prettierrc.js
    在根目录下面添加.prettierrc.js文件夹,然后将下面的配置添加到其中。如果不想格式化某些文件可以再添加一个.prettierignore的文件,用法和.gitignore文件差不多,将不需要格式化的文件夹或文件通过正则匹配或者具名的方式添加进去,这样就不会格式化对应的文件了。
js
/** .prettierrc.js
 * 在VSCode中安装prettier插件 打开插件配置填写`.prettierrc.js` 将本文件作为其代码格式化规范
 * 在本文件中修改格式化规则,不会同时触发改变ESLint代码检查,所以每次修改本文件需要重启VSCode,ESLint检查才能同步代码格式化
 * 需要相应的代码格式化规范请自行查阅配置,下面为默认项目配置
 */
module.exports = {
	// 一行最多多少个字符
	printWidth: 150,
	// 指定每个缩进级别的空格数
	tabWidth: 2,
	// 使用制表符而不是空格缩进行
	useTabs: true,
	// 在语句末尾是否需要分号
	semi: true,
	// 是否使用单引号
	singleQuote: true,
	// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
	quoteProps: 'as-needed',
	// 在JSX中使用单引号而不是双引号
	jsxSingleQuote: false,
	// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
	trailingComma: 'es5',
	// 在对象文字中的括号之间打印空格
	bracketSpacing: true,
	// jsx 标签的反尖括号需要换行
	jsxBracketSameLine: false,
	// 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
	arrowParens: 'always',
	// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
	rangeStart: 0,
	rangeEnd: Infinity,
	// 指定要使用的解析器,不需要写文件开头的 @prettier
	requirePragma: false,
	// 不需要自动在文件开头插入 @prettier
	insertPragma: false,
	// 使用默认的折行标准 always\never\preserve
	proseWrap: 'preserve',
	// 指定HTML文件的全局空格敏感度 css\strict\ignore
	htmlWhitespaceSensitivity: 'css',
	// Vue文件脚本和样式标签缩进
	vueIndentScriptAndStyle: false,
	//在 windows 操作系统中换行符通常是回车 (CR) 加换行分隔符 (LF),也就是回车换行(CRLF),
	//然而在 Linux 和 Unix 中只使用简单的换行分隔符 (LF)。
	//对应的控制字符为 "\n" (LF) 和 "\r\n"(CRLF)。auto意为保持现有的行尾
	// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
	endOfLine: 'auto',
};

TIP

如果 vite 的 package.json 有 "type": "module" 字段的话,那么eslint 和 prettier 配置文件格式应该是 .cjs。而不是 .js

TIP

prettierrrc 每次修改完成后需要重启 vscode,才能保证和 eslint 检查同步更新。

  1. VsCode安装prettier插件

六、Prettier 结合 ESLint

当你在项目中同时使用 Prettier 和 ESLint 的时候,两者往往会存在一些配置上的冲突。也就是在你保存的时候能看到代码被格式化了两次,一次是 ESlint 的格式化,一次是 Prettier 的格式化(当两者的针对同一个配置存在不同方案的时候)。

所以为了解决这种冲突,我们需要使用到 config-prettier + eslint-plugin-prettier。

  • eslint-config-prettier 的作用是关闭 eslint 中与 prettier 相互冲突的规则。
  • eslint-plugin-prettier 的作用是赋予eslint 用 prettier 格式化代码的能力。 安装依赖并修改 .eslintrc 文件

安装依赖

pnpm add eslint-config-prettier eslint-plugin-prettier -D

配置 eslint

// plugin:prettier/recommended
{
    "extends": ["eslint:recommended", "standard",  "plugin:prettier/recommended"]
}

参考文献

ESLint 使用教程