ESLint 在中大型团队的应用实践
使用背景
代码规范是软件开发领域经久不衰的话题,几乎所有工程师在开发过程中都会遇到,并或多或少会思考过这一问题。随着前端应用的大型化和复杂化,越来越多的前端工程师和团队开始重视 JavaScript 代码规范。
主要解决的问题:
对于独立开发者,或者执行力较强、技术场景较为单一的小型团队而言,直接使用 ESLint 及其生态提供的一些标准方案,可以用较低成本来实现 JavaScript 代码规范的落地。如果再搭配一些辅助工具(例如 husky 和 lint-staged),整个流程会更加顺畅。ESLint对工程代码进行静态检查,发现和修复不符合规范的代码。如果想降低配置成本,也可以直接使用开源配置方案,例如 eslint-config-airbnb 或 eslint-config-standard。
一、理解代码检查
代码检查,顾名思义就是检查代码,发生于开发阶段,可有效帮助开发者减少 JavaScript 粗心代码,如语法错误、变量未定义、变量未使用等等问题。除此之外,代码检查还可以约束统一开发人员的代码风格,利于团队协作。我们再从三个方面来展开分析,加深对代码检查的实践理解。这三个方面分别为以下三点:
-
1)代码检查的功能
-
2)代码检查的类型
-
3)代码检查的工具
1、代码检查的功能
代码检查这个切面大概可以帮助我们做以下三件事情:
- 语言语法检查:比如检查出字符串引号或者函数调用括号没有匹配等问题。
- 编码错误检查:比如检查出开发者在使用一个不存在的变量或者变量定义了却没有使用等问题。
- 代码风格检查:比如检查出开发者没有使用分号(与所选风格有关)等问题。
2、代码检查的方式
以代码检查发生的不同时间和场景来划分,我把代码检查的方式分类成以下四种:
- 编码时检查:编写代码时检查,通常表现为由 IDE 自动实时检查并进行代码提示。
- 编码后检查:编写代码后检查,通常表现为手动调用检查脚本 / 工具进行代码的检查或者代码保存后由 IDE 自动检查当前文件。
- 构建前检查:构建执行前检查,通常表现为将代码检查作为构建任务的一个前置切面,构建时自动触发代码检查。
- 提交前检查:git commit 前检查,通常表现为将代码检查作为 git commit 的一个 hooks 任务,代码提交前自动触发代码检查。
理解代码检查的方式很重要,这直接反映对代码检查这个概念本身的掌握程度。
3、代码检查工具
代码检查的实现通常不会仅仅是字符串分析处理,这其中会大量涉及到语法分析。既然涉及到语法,那么就需要对不同的代码使用不同的代码检查工具,通常来说,我们会使用 Eslint 工具来实现对 JavaScript 和 Typescript 代码的检查,使用 stylelint 工具对样式代码进行代码检查。
二、ESLint 特性简介
目前较为通用的方案——ESLint,它是一款插件化的 JavaScript 代码静态检查工具,其核心是通过对代码解析得到的 AST(Abstract Syntax Tree,抽象语法树)进行模式匹配,定位不符合约定规范的代码。
1、插件化
下图简单地描述了 ESLint 的工作过程:
ESLint 的能力更像一个引擎,通过提供的基础检测能力和模式约束,推动代码检测流程的运转。
原始代码经过解析器的解析,在管道中逐一经过所有规则的检查,最终检测出所有不符合规范的代码,并输出为报告。
借助插件化的设计,不但可以对所有的规则进行独立的控制,还可以定制和引入新的规则。
ESLint 本身并未和解析器强绑定,我们可以使用不同的解析器进行原始代码解析,例如可以使用 babel-eslint 支持更新版本、不同阶段的 ES 语法,支持 JSX 等特殊语法,甚至可以借助 @typescript-eslint/parser 支持 TypeScript 语言的检查。
2、配置能力全面、可层叠、可共享
ESLint 提供了全面、灵活的配置能力,可以对解析器、规则、环境、全局变量等进行配置;可以快速引入另一份配置,和当前配置层叠组合为新的配置;还可以将配置好的规则集发布为 npm 包,在工程内快速应用。
3、社区生态较为成熟
开源社区中基于 ESLint 的项目非常多,既有针对各种场景、框架的插件,也有各种 ESLint 规则配置方案,基本可以涵盖前端开发的所有场景。
4、规范配置方案设计
基于 ESLint 的插件化、可层叠配置特性,以及面向各种场景、框架的开源方案,如下图所示的 ESLint 配置架构:
该配置架构采用了分层、分类的结构,其中:
-
基础层:制定统一的基础语法和格式规范,提供通用的代码风格和语法规则配置,例如缩进、尾逗号等等。
-
框架支撑层(可选):提供对通用的一些技术场景、框架的支持,包括 Node.js、react、vue、React Native 等;这一层借助开源社区的各种插件进行配置,并对各种框架的规则都进行了一定的调整。
-
TypeScript 层(可选):这一层借助typescript-eslint,提供对 TypeScript 的支持。
-
适配层(可选):提供对特殊场景的定制化支持,例如 MRN(美团内部的 React Native 定制化方案)、配合 prettier 使用、或者某些团队的特殊规则诉求。