早在 1978 年,Stephen C. Johnson 在 Debug 自己的 C 语言项目时,突然想到为什么不做一个工具来提示自己写的代码哪里有问题呢?

这个工具也被称为 Linter。Linter 本意指的是衣服上多出来的小球、绒毛和纤维等。

Linter 想要提示错误,首先就得阅读代码,这也是为什么 Linter 也被称为静态代码分析的工具。阅读完之后,再加上人为自定义的一些规则,那么 Linter 就拥有了提示错误的能力。

JavaScript Linter 发展史

JSLint

在 2002 年,Douglas Crockford 就为 JavaScript 写了第一个 Linter 工具:JSLint

JSLint 的优点就是开箱即用,不需要配置太多的东西,相当于拎包入住。但优点也是缺点,就是规则太严格,完全不可扩展和自定义配置,连配置文件都没有。

JSHint

2010 年 Anton Kovalyov 和其他人,在 JSLint 的基础上 fork 了一份,改造成了 JSHint

这个工具与 JSLint 的思路正好相反,它的默认规则非常松散,自由度非常高。但是也同样带来了问题:需要非常了解这些规则才能配出一个好用的规则表。因为规则太不严格,过于自由,所以单纯靠默认的规则跟没有配置 Linter 一样。

JSCS

前面的 JSLint 和 JSHint 主要功能都是检查代码质量问题,JSCS(JavaScript Coding Style)则是一个代码风格检查器。

它有超过 90 条规则,也能自己创建规则,不过这些规则主要是和代码风格、代码格式化有关,它不会报任何和 JS 代码质量相关的错误。

尽管 JSCS 在其活跃时期非常受欢迎,但它已于 2016 年被宣布停止维护,并建议用户迁移到 ESLint。ESLint 是一个更强大、更灵活的工具,它不仅可以检查代码风格,还可以发现潜在的错误和代码质量问题。另一个流行的代码格式化工具是 Prettier,它专注于自动格式化代码,而不提供任何代码质量检查。

虽然 JSCS 不再被维护,但它的一些功能和理念已经被 ESLint 和 Prettier 等现代工具所采纳。如果你正在寻找一个代码风格检查器和格式化器,建议使用 ESLint 和 Prettier 来替代 JSCS。这两个工具可以很好地协同工作,ESLint 负责检查代码质量,而 Prettier 负责格式化。

ESLint

2013 年,一个叫 JSChecker 的小项目被改名成我们如今非常熟悉的 ESLint。

ES6 上线之后,JSHint 就受不了直接投降了,因为它不支持这些 ES6 新语法。而 ESLint 正好异军突起,马上用 Esprima (一个高性能的 ECMAScript parser)支持所有 ES6 新语法,并对新语法做好了校验。

除了基础的 ES6 代码质量校验,ESLint 还支持代码风格的规则。开发者不仅可以自定义项目要用哪些规则,也能直接使用社区上制定的规则(比如 eslint-config-airbnb)。

这一波操作也让 ESLint 成为现在 JavaScript 首选的 Linter 了。然而,关于 Linter 的故事还没结束。

2012 年微软公布了第一版的 TypeScript,随之而来的还有一个叫 TSLint 的 Linter。

在那段时间里,TSLint 是 TypeScript 的标准 Linter 工具,ESLint 则是 JavaScript 标准 Linter。它们各有自身特色:ESLint 有 TSLint 所没有的一些语法特性支持,而 TSLint 可以对代码进行静态分析和类型检查。

可是,一份代码还要两个 Linter 并行检查属实有点让人不爽。TSLint 也经常和 ESLint 的人探讨应该用哪个作为主力 Linter。TS 的社区也有很多声音希望优先满足 JSer 的需求,毕竟 TS 是 JS 的超集,还是以 ESLint 为主。

最终,在 2019 年 TSLint 宣告不再维护,ESLint 支持 TypeScript。

ESLint 核心概念

ESLint 的核心概念包括以下几点:

  1. 规则(Rules):规则是 ESLint 的核心,它们是独立的脚本,用于检查代码中的特定问题。ESLint 有许多内置规则,这些规则可以覆盖各种编码风格和潜在错误。规则是可配置的,每个规则可以被启用或禁用,并可以设置为警告或错误级别。
  2. 配置(Configuration):ESLint 允许通过配置文件自定义规则的启用和设置。配置文件可以是 .eslintrc.* 格式的文件或 package.json 文件里的 eslintConfig 字段。配置可以继承其他配置,这使得可以轻松地共享和组合规则集。共享配置通常是一个 npm 包,可以被多个项目使用。
  3. 插件(Plugins):插件是可扩展 ESLint 功能的方式,它们包含一组自定义规则和/或处理器。这使得 ESLint 可以适应不同的编码风格和技术栈。插件可以通过 npm 安装并在配置文件中引用。
  4. 处理器(Processors):处理器是一个可选的插件特性,它可以对非 JavaScript 文件进行预处理,以便 ESLint 可以检查这些文件中嵌入的 JavaScript 代码。例如,HTML 文件中的 <script> 标签或 Markdown 文件中的代码块。
  5. 命令行接口(CLI):ESLint 提供了一个命令行接口,用于在终端中执行 linting 操作。CLI 允许用户指定一个或多个文件、目录或 glob 模式 以进行检查。CLI 还支持许多选项,这些选项可以覆盖配置文件中的设置,如禁用特定规则、规定输出格式等。

ESLint 快速上手

首先创建一个 eslint-demo 的项目,使用 pnpm init 进行初始化,安装 ESLint:

pnpm add eslint -D

然后在项目根目录下面创建一个 ESLint 的配置文件 .eslintrc,里面会书写一些配置信息:

{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": "eslint:recommended",
  "parserOptions": {
    "ecmaVersion": 12,
    "sourceType": "module"
  },
  "rules": {
    "indent": ["error", 2],
    "quotes": ["error", "single"],
    "semi": ["error", "never"]
  }
}
  • env:主要是定义预设的全局变量
    • browser:这份配置适用于浏览器环境,预定义了诸如 windowdocument 之类的浏览器全局变量
    • es2021: 表示使用的是 ES2021 标准,会预定义一些新版本的全局变量,如 PromiseSymbol
  • extends:ESLint 配置继承,eslint:recommended 是 ESLint 团队推荐的一组核心规则
  • parserOptions:和解析器相关的配置
    • ecmaVersion:使用的 ECMAScript 的版本,12 就是 2021
    • sourceType:模块类型,这里设置为 module,表示使用的 ESM 模块规则,支持 importexport 语法
  • rules:定义代码风格,功能类似于 Prettier
    • indent:缩进,这里设置的是两个空格,如果不符合要求,会报 error 类型的错误
    • quotes:引号的设置,这里设置的是单引号,如果不符合要求,会报 error 类型的错误
    • semi:在没有 ASI 风险情况下,不需要插入分号,如果不符合要求,会报 error 类型的错误

最后修改 package.json,添加如下的 script 脚本命令:

"scripts": {
    // ...
    "lint": "eslint ./src"
},

使用 ESlint 进行代码检查的时候,是支持自动修复的,但是并非所有的错误都能够自动修复,只能够修复一部分。

要自动进行修复,只需要添加命令行参数 --fix 即可。