阅读本文您将收获:

  1. 了解 ESLint 预置函数的设计思路。
  2. 了解 ESLint 预置函数实现的具体过程。
  3. 了解 ESLint 预置函数在实际项目中的应用。

预置函数基于 ESLint v9.x,若版本在此之前,请查看迁移指南

设计比较简单,ESLint 配置文件 eslint.config.js 中,直接调用预置函数 preset 并导出其返回结果。

preset 函数允许针对特定项目场景,传入自定义的配置规则,覆盖预置规则。

preset 函数中预置了一系列 ESLint 规则配置,主要分为两部分 - 默认启用配置按需启用配置

默认启用配置 包括大多数项目都需要的基础配置,诸如 javascriptTypescriptignores 等相关配置。

按需启用配置 依赖项目技术栈,将决定权交于用户,可通过设置对应的启用选项参数,按需启用,如 VueJSONMarkdownPrettier 等相关配置。

preset 函数内部将 自定义规则预置规则 进行整合,输出最终配置。

为达到 一次封装,到处可用 的目的,我们将预置函数封装成库。

工程初始化

以下涉及的执行语句,均在终端命令行输入,回车执行

  1. 新建项目目录
 1mkdir eslint-config
 2cd eslint-config

执行成功后,会创建一个 eslint-config 空目录并跳转进入。

  1. npm 初始化
 1npm init -y

执行成功后,会在根目录下自动生成 package.json 文件。

  1. typescript 初始化
 1pnpm add typescript -D
 2tsc init

执行成功后,会在根目录下自动生成 tsconfig.json 文件,并带有默认配置。

  1. 创建目录结构

基础结构如下:

 1mkdir src
 2cd src
 3touch index.ts

eslint.config.ts 暂且先不创建,预置函数封装完成后再处理。

OK,初始项目到此结束。

定义预置函数 preset

定义预置函数前,首先要考虑两个问题:

  • 预置函数应该接收哪些 参数
  • 预置函数应该返回什么 结果

参数

从设计可知,preset 函数允许以下操作:

  • 自定义 ESLint 配置。
  • 启用特定技术栈的 ESLint 配置。

因此 preset 至少要支持两个参数:

  • config:自定义配置,优先级最高,可覆盖预置配置。
  • envOptions:环境配置选项,可包含诸如 prettiervuejsonmarkdown 等,用于启用对应技术栈的预置 ESLint 配置。

结果

从设计可知,preset 函数返回的结果,可以被 eslint.config.js 直接导出并生效,因为 Eslint V9.x 配置文件导出的是 平铺结构,即 数组,所以 preset 函数返回的结果,就是包含完整 ESLint 配置的数组。

preset 函数基础结构定义如下:

 1 * eslint config 预置函数
 2 *
 3 * @param config 覆盖配置
 4 * @param evnOptions 环境配置项可接受单个配置对象或多个配置数组
 5 * @returns
 6 */
 7export function preset(config: Linter.Config | Linter.Config[] = [], envOptions: EnvOptions = {}) {
 8  
 9  const configs: Linter.Config[] = []
10
11  
12
13  
14  const hasCustomConfig = Array.isArray(config)
15    ? config.length > 0
16    : Object.keys(config).length > 0
17  if (hasCustomConfig) {
18    configs.push(...(Array.isArray(config) ? config : [config]))
19  }
20
21  return configs
22}

默认启用配置

封装配置

上文提到,默认启用配置 是指那些大多数项目都需要启用的 ESLint 规则,包括但不限于 JavscriptTypescriptignoresnode 等相关规则。

本文以两个比较直观的 Javscript 规则为例:

 1eqeqeq: ['error', 'smart'] // 要求代码中相等运算符必须使用全等,即 ===
 2'no-debugger': 'warn' // 要求代码中不能出现 debugger 调试语句

src 下创建 configs 目录,用来维护各种类型的 ESLint 预置配置文件。

 1mkdir configs

configs 目录下新建 javascript.ts 文件,用来维护 Javascript 预置配置。

 1cd configs
 2touch javascript.ts

javascript.ts 中写入以下代码,导出 javascript 预置配置对象 - javascriptConfigs

 1import globals from 'globals'
 2
 3export const javascriptConfigs: Linter.Config[] = [
 4  {
 5    languageOptions: {
 6      globals: {
 7        ...globals.browser
 8      },
 9    },
10    plugins: {},
11    rules: {
12      eqeqeq: ['error', 'smart'],
13      'no-debugger': 'warn'
14    },
15  },
16]

注:globals 是一个比较全面的涵盖多个环境全局变量的依赖包,包括但不限于浏览器环境,node 环境等。执行 pnpm add globals -S 安装。

篇幅所致,本文定义的 Javascript 规则比较简单,实际项目可基于风格要求自行扩展,比如在 rules 配置内补充规则,在 plugins 配置内引用现有插件等等。

整合配置

将默认规则添加到 preset 函数中:

 1import { javascriptConfigs } from './configs/javascript'
 2
 3
 4const BasicConfigs = [ ...javascriptConfigs ]
 5
 6export function preset(config: Linter.Config | Linter.Config[] = [], envOptions: EnvOptions = {}) {
 7  
 8  const configs: Linter.Config[] = [ ...BasicConfigs ]
 9
10  
11
12  
13
14  return configs
15}

按需启用配置

封装配置

按需启用配置 依赖项目应用技术栈,交由用户决定是否启用。

我们以相对简单的配置 - Prettier 为例。

尽管目前大多项目都结合使用 ESLintPrettier,以加强对代码质量的管理,然而 Prettier 并不是必选项,所以可将其作为按需规则之一。

Prettier 配置涉及两个相关插件:

终端输入以下命令安装依赖:

 1pnpm add eslint-plugin-prettier eslint-config-prettier -S

configs 目录下新增 prettier.ts,用于维护 Prettier 相关配置:

 1cd configs
 2touch prettier.ts

prettier.ts 中写入以下代码,导出 Prettier 预置配置对象 - prettierConfigs

 1import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
 2import eslintConfigPrettier from 'eslint-config-prettier'
 3
 4export const prettierConfigs: Linter.Config[] = [
 5  eslintPluginPrettierRecommended,
 6  eslintConfigPrettier
 7]

方便起见,直接使用 eslint-plugin-prettier 的推荐配置(recommended),结合 eslint-config-prettier 提供的配置解决与 ESLint 规则的冲突问题。

到这,基础的 Prettier 配置就搞定了,若插件默认的规则不符合项目要求,可在后面追加自定义的规则对象。例如:

 1export const prettierConfigs: Linter.Config[] = [
 2  eslintPluginPrettierRecommended,
 3  eslintConfigPrettier,
 4  {
 5      rules: {
 6          'prettier/prettier': 'warn'
 7      }
 8  }
 9]

整合配置

现在将 Prettier 配置添加预置函数 preset 中,分为以下两步:

  1. preset 第二个参数 envOptions 新增 prettier 选项,用于设置是否启用 Prettier 相关配置,默认 true,即 启用

  2. preset 内部判断 prettier 选项是否为 true,若是,则将 Prettier 配置加入到最终配置 configs 中。

 1import { javascriptConfigs, prettierConfigs } from './configs/javascript'
 2
 3
 4const BasicConfigs = [ ...javascriptConfigs ]
 5
 6export function preset(config: Linter.Config | Linter.Config[] = [], {
 7    prettier: enablePrettier = true
 8}: EnvOptions = {}) {
 9  
10  const configs: Linter.Config[] = [ ...BasicConfigs ]
11
12  if (enablePrettier) {
13      configs.push(...prettierConfigs)
14  }
15
16  
17
18  
19
20  return configs
21}

优化项

工具雏形已成,接下来就是在此基础上进行扩展完善,以适应更广泛的应用场景。

集成更多环境配置

一个前端项目,应用的技术多种多样,可针对项目需要,扩展工具内置配置项。

比如 TypeScriptVueReactJSONMarkdown 等,都是前端项目常用的技术栈,因此相关的 ESLint 配置也很有必要集成在工具内。

导出配置

对于某些特殊情况,如对已有 ESLint 配置的增强、完善,可能不想用 preset 函数,仅引用部分规则配置到项目中。

因此可以将工具内置的 ESLint 配置按类导出,供用户按需引入,添加到已有的 ESLint 配置文件中(eslint.config.js)中。

preset 自动判断是否启用按需配置

preset 函数第二个参数 envOptions 涉及按需启用配置选项,如 vue,除了直接给定默认值的方式外,还可通过 扫描项目依赖,自动判断是否启用。

例如:

 1import { isPackageExists } from 'local-pkg'
 2
 3
 4export const hasVue = isPackageExists('vue') || isPackageExists('nuxt')

preset 函数中使用:

 1export function preset(config: Linter.Config | Linter.Config[] = [], {
 2    prettier: enablePrettier = true,
 3    vue: enableVue = hasVue
 4}: EnvOptions = {}) {
 5  
 6  
 7  if (enableVue) {
 8      
 9  }
10  
11  
12}

其他…

代码写好了,测试环节不能少,起码要意思意思。我们直接在当前工程应用,毕竟本项目也要注意代码质量。

本文开头 「工程初始化」部分留了个尾巴,没创建 ESLint 配置文件,现在来完成它。

两步搞定 ESLint 配置:

  1. 根目录下新增 eslint-config.js
 1touch eslint-config.js
  1. eslint-config.js 写入以下代码:
 1import { preset } from './dist/index.js'
 2
 3export default preset()

./dist/index.js 是编译后的 js 文件。

OK,ESLint 配置搞定,就这么简单。

配置生效的前提需要确保相关依赖已全部安装,如 eslintprettier 等,安装过程就不赘述了,点击查看官网即可。

src/index.ts 写一点不符合规则的代码,比如:

 1if (a == 0) {
 2    debugger
 3}

此时会发现,VSCode 标记了不合格的代码,鼠标放到问题代码上,会提示不满足的规则配置。

本文重点介绍了 ESLint 预置函数工具的开发过程,包括基础的设计思路,简单的配置整合及粗略的应用演示,旨在帮助同学们加深对于 ESLint 预置函数这东西的了解和应用。希望对您有所帮助。相关代码将上传至 GitHub,欢迎 star

个人笔记记录 2021 ~ 2025