ESLint如何搭配编辑器和第三方依赖进行代码自动格式化

1,646 阅读8分钟

参考帖:

在Typescript项目中,如何优雅的使用ESLint和Prettier

我的electron教程系列

在 Vue + Typescript 项目中使用 eslint 和 Prettier 的配置

Using ESLint and Prettier in a TypeScript Project

最后有ESLint + TS + Prettier的完整配置及需要的依赖和编辑器插件

ESLint核心依赖、编辑器插件和Webpack中的ESLintWebpackPlugin之间的关系

我们先不关心ESLint的具体配置,从整体上来看,先了解编辑器+ESLint+打包工具的整体生态链 如果你使用其他的编辑器或者打包工具,可以在这里查询ESLint的相关整合插件/依赖

ESLint核心依赖

依赖下载:npm install eslint -D 在我们编写项目的时候,直观的感受上ESLint会做以下事情:

  1. 检查语法错误
  2. 将错误输出到控制台
  3. 开发环境页面上增加一个错误modal
  4. 生产环境发现error,直接停止打包运行
  5. 文件保存时格式化(可以配合prettier)

但是实际上,这些操作并不是ESLint单独完成的,其中ESLint完成的核心步骤是检查语法错误,识别了文件中的错误后,才能进行后面的操作,错误检查步骤:

  1. 通过定义的解析器(parser)去解析文件,生成AST树
  2. 通过预设/自定的规则对错误进行归类(error、warning)

这个网站可以让你直观的理解各种解析器和AST树 astexplorer.net/

错误检查只能将错误找出来,并不会进行任何操作,这时候控制台不会报错,编辑器也不会标红代码,这个功能主要是由ESLint核心依赖提供,也就是说,项目中通过npm install eslint -D下载ESLint依赖并进行配置之后,就拥有根据配置查找到错误的能力,但是具体需要如何展示这些错误,就需要另外的插件支持。

VSCode插件-ESLint

下载:VSCode应用商店搜索eslint

功能:当代码不符合eslint配置的规范时,标红代码,或是开启一系列eslint相关的配置,比如ESLint保存自动调用代码修复(--fix)功能就需要编辑器的支持

以VSCode为例,下载ESlint插件后需要在首选项-设置中配置编辑器需要检测的文件类型,如果不配置是不生效的

// ESLint插件的基本配置 settings.json
{
	"eslint.validate": [
		"javascript",
		"typescript",
		"javascriptreact",     // JSX 
		"typescriptreact"		// TSX
	]
// 保存自动调用eslint --fix [file],该功能由VSCode的ESLint插件提供
	"editor.codeActionOnSave": {
		"source.fixAll.eslint": true
	}

Webpack插件 ESLintWebpackPlugin

下载:npm install eslint-webpack-plugin —save-dev

功能:webpack插件,项目在打包时如果遇到eslint检查出的语法错误,在开发环境:控制台打印报错信息,可以在页面中嵌入全屏modal,展示错误信息;在生产环境:可中止打包运行。 可以通过改变ESLintWebpackPlugin的配置来改变具体处理的方式。ESLintWebpackPlugin

可以这么理解,如果使用Webpack打包项目,借助webpack-dev-server启动本地开发环境,那么开发环境下控制台的打印信息是受到webpack控制的,Webpack并不知道ESLint的报错信息有哪些,必须通过一个桥梁,也就是eslint-webpack-plugin来建立它们的连接。生产环境下也是同理。

如何在项目中配置ESLint、Typescript以及Prettier

基本思路

上面介绍的ESLint+编辑器+打包工具的三个依赖,其实已经可以满足我们格式化代码的所有要求

如果项目中想要用Prettier来进行代码格式化,有两种方式,一种是Prettier为ESLint提供规则,使用ESLint的fix功能去格式化代码;第二种方式是先使用Prettier为ESLint提供规则,再借助编辑器的Prettier插件,用相同的prettier规则来格式化代码

我们项目中使用第一种方式,单纯只用Prettier来提供规则,这样的好处是项目的格式化配置结构更清晰,也不需要下载多余的编辑器插件

格式化的思路如下:

  1. ESLint读取配置文件.eslintrc.js来检查代码中不符合规范的错误或警告
  2. 配置编辑器(VSCode),开启文件的保存自动修复功能(自动—-fix),只有一些特定的错误可以被自动修复,比如分号、冒号等

无论你使用Vue、typescript或React,格式化代码的步骤都完全一样,他们的区别只在于第一步中,ESLint是如何去定义这些错误的,也就是说,针对于不同的技术栈,只有ESLint的配置不一样而已,这也是为什么ESLint的相关插件那么多的原因

先看一下ESLint的基本配置,这是一份没有添加任何额外插件的配置:

// .eslintrc.js
module.exports = {
	// enviroment 项目运行的环境,配置这个可以为你提供一些全局变量,比如browser环境下允许使用windows API
	env: {
		browser: true,
		node: true
	},
	parser: 'espree', // eslint的默认解析器
	extends: ['eslint:recommended'], // 启用eslint的一些核心规则,也可以根据项目需求添加其他预设的规则
	rules: { // 用户自定义的规则,可以覆盖extends中配置的预设规则
		semi: ["error", "always"],
                quotes: ["error", "double"]
	},
	plugins: [] // 第三方插件,可以提供额外规则、预设配置(config)、全局环境变量等
}

整个ESLint配置的最终目的是制定一份规则,然后检查代码是否符合该规则,针对某些规则,如果错误等级为error,可以通过eslint --fix来修复文件 这份配置文件可以分两部分,其中:

  • envextendsrulesplugins字段都是为了规则服务
  • parser字段指定解析器,用于生成AST树,ESLint的默认解析器是espree,只能解析JS文件,无法识别ts文件,项目文件如果使用typescript就需要借助第三方依赖来改变解析器

添加typescript检测

相关依赖

module.exports = {
	env: {
            browser: true,
            node: true
	},
	parser: '@typescript-eslint/parser', // 使用typescript解析器
	extends: [
            'eslint:recommended', 
            'plugin:@typescript-eslint/recommended'
        ], // 增加typescript的核心规则
        
        plugins: ['@typescript-eslint'] // 添加typescript插件,这样就可以使用typescript的规则
	rules: {
		semi: ["error", "always"],
     quotes: ["error", "double"],
		'@typescript-eslint/no-explicit-any': 0  // typescript的规则
	},
}

添加Prettier规则

相关依赖

  • eslint-config-prettier 解决ESLint中的样式规范和prettier中样式规范的冲突,以prettier的样式规范为准,使ESLint中的样式规范自动失效
  • eslint-plugin-prettier关闭ESLint和Prettier有冲突的规则 加入Prettier规则检测后的配置 要注意的一点是extends数组中后面的配置项会覆盖前面的,prettier必须放在最后一项,保证fix的修复规则以prettier为准
module.exports = {
	env: {
            browser: true,
            node: true
	},
	parser: '@typescript-eslint/parser', 
	extends: [
            'eslint:recommended', 
            'plugin:@typescript-eslint/recommended', 
            'prettier'
        ], // 增加Prettier的核心规则
        plugins: ['@typescript-eslint', 'prettier'],   // 添加prettier插件来提供prettier的rule
	rules: {
		// semi: ["error", "always"],
     // quotes: ["error", "double"],  // rules里的规则会覆盖extends中的规则,要删掉这些影响格式化的规则
		'@typescript-eslint/no-explicit-any': 'error',
		'prettier/prettier': 'error',  // 配置prettier的错误等级为error,为了让exlint --fix可以修复其错误
		'arrow-body-style': 'off',
		'prefer-arrow-callback': 'off'
	},
}

eslint-plugin-prettier提供了一个快捷配置,下面的prettier配置和上面的配置效果一样:

module.exports = {
	env: {
            browser: true,
            node: true
	},
	parser: '@typescript-eslint/parser', 
	extends: [
            'eslint:recommended', 
            'plugin:@typescript-eslint/recommended', 
            'plugin:prettier/recommended'
        ], // 增加Prettier的核心规则
        plugins: ['@typescript-eslint'], 
	rules: {
            // semi: ["error", "always"],
            // quotes: ["error", "double"],
            '@typescript-eslint/no-explicit-any': 'error',
	},
}

arrow-body-styleprefer-arrow-callback这两个规则是prettier推荐添关闭的,在某些情况下,这两个规则会导致ESLint autofix的BUG

If you use arrow-body-style or prefer-arrow-callback together with the prettier/prettier rule from this plugin, you can in some cases end up with invalid code due to a bug in ESLint’s autofix – see issue #65 .

-- 摘自eslint-plugin-prettier官方文档

Prettier会读取项目根目录下的.prettierrc.js的配置作为自己的规则,这些定义的规则也会覆盖掉extends中的预设规则,如果遇到配置不生效的情况,关掉编辑器重新打开即可

module.exports = {
    semi: false,
    trailingComma: 'all',
    endOfLine: 'auto',
    tabWidth: 2,
    singleQuote: true
    // ... 可参考官方配置
}

这样就完成了ESLint+Typescript+Prettier的格式化配置,如果你的项目使用了Vue或React或是其他技术栈,只需要修改一下ESLint的规则即可,建议配置时根据自己的项目在这里挑选符合自己的依赖包

项目需要的依赖:

  • eslint
  • prettier
  • typescript
  • @typescript-eslint/parser
  • @typescript-eslint/eslint-plugin
  • eslint-config-prettier
  • eslint-plugin-prettier

编辑器需要的插件(我们选择使用eslint来做autofix,不需要prettier插件)

  • eslint
  • typescript

完整的配置:

// .eslintrc.js
module.exports = {
	env: {
            browser: true,
            node: true
	},
	parser: '@typescript-eslint/parser', 
	extends: [
            'eslint:recommended', 
            'plugin:@typescript-eslint/recommended', 
            'plugin:prettier/recommended'
        ], // 增加Prettier的核心规则
        plugins: ['@typescript-eslint'], 
	rules: {
            // semi: ["error", "always"],
            // quotes: ["error", "double"],
            '@typescript-eslint/no-explicit-any': 'error',
	},
}

// setting.json
{
    "eslint.validate": [
        "javascript",
        "typescript",
        "javascriptreact",     
        "typescriptreact"
    ],
    // 文件保存自动调用eslint --fix
    "editor.codeActionOnSave": {
        "source.fixAll.eslint": true
    }
}
// .prettierrc.js
module.exports = {
    semi: false,
    trailingComma: 'all',
    endOfLine: 'auto',
    tabWidth: 2,
    singleQuote: true
    // ... 可参考官方配置
}

每次配置eslint都觉得依赖很多,但其实它的整体流程很简单,配置文件也不多

希望这篇文章可以帮助你理解ESLint是如何搭配其他插件完成代码格式化的

计划之后会加入git的提交验证,测试完后会写一篇文档来记录