ESLint Flat Config 工程化实战:从规则配置到团队代码规范落地

摘要

深入ESLint v10 Flat Config,解析defineConfig、files匹配、rules规则等级与typescript-eslint集成,用统一配置强制团队代码风格一致、避免bug。


ESLint 是前端工程化中代码质量管控的核心工具。它强制团队写出一致风格的代码,在开发和代码审查阶段拦截潜在的 bug。ESLint v9 引入的 Flat Config 体系彻底取代了传统的 .eslintrc 多层配置,用单一的 eslint.config.mjs 统一管理所有规则。

项目初始化与技术栈

一个最小化的 ESLint 工程由几个文件组成:

csharp 复制代码
eslint-demo/
├── eslint.config.mjs    # Flat Config 配置文件
├── index.mjs            # 待检查的代码
├── package.json
└── pnpm-lock.yaml

依赖项集中在 devDependencies 中------ESLint 是开发时工具,不参与生产构建:

json 复制代码
{
  "devDependencies": {
    "@eslint/js": "^10.0.1",
    "eslint": "^10.8.1",
    "globals": "^17.11.0",
    "typescript-eslint": "^8.67.0"
  }
}

eslint 是核心引擎,@eslint/js 提供 JavaScript 推荐的规则预设,globals 提供各种运行时的全局变量定义,typescript-eslint 提供 TypeScript 相关的规则和解析器。

Flat Config 的入口结构

eslint.config.mjs 是 ESLint 配置的单一入口。ESLint v9 之后不再读取 .eslintrc.eslintrc.jsoneslintConfig 字段,全部集中在 eslint.config.mjs 中:

javascript 复制代码
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import { defineConfig } from "eslint/config";

export default defineConfig([
  { 
    files: ["**/*.{js,mjs,cjs,ts,mts,cts}"], 
    plugins: { js }, 
    extends: ["js/recommended"], 
    languageOptions: { globals: globals.node },
    rules: {
      "no-var": 2,
      "no-console": 1,
      "quotes": ["error", "double"],
      "semi": ["error", "always"],
      "indent": ["error", 2],
    },
  },
  tseslint.configs.recommended,
]);

defineConfig 接受一个数组,数组中的每个元素是一个配置对象或预设。配置对象是按顺序合并的------后面的配置会覆盖或补充前面的配置。这种设计让配置组合变得透明:基础预设 + 自定义规则 + 扩展预设,按优先级排列。

files 匹配:精确控制作用范围

files 字段指定了当前配置块适用的文件范围。["**/*.{js,mjs,cjs,ts,mts,cts}"] 匹配所有 JavaScript 和 TypeScript 文件------** 递归匹配任意层级的目录,{js,mjs,cjs,ts,mts,cts} 列出所有支持的扩展名。

如果项目有不同的文件类型需要不同的规则(比如测试文件 *.test.js 允许 console.log,而生产代码禁止),可以拆分为多个配置块,每个配置块使用不同的 files 匹配模式。

globals:声明运行环境

languageOptions: { globals: globals.node } 声明了代码的运行环境是 Node.js。globals 包提供了多个预定义的环境变量集合:

  • globals.node ------ Node.js 内置全局变量(processBuffer__dirname 等)
  • globals.browser ------ 浏览器全局变量(windowdocumentfetch 等)
  • globals.es2021 ------ ES2021 标准全局变量
  • globals.jest ------ Jest 测试框架全局变量

如果代码使用了某个环境下的全局变量但没有声明,ESLint 会报 no-undef 错误。例如,在 Node.js 环境中使用 window 会被标记为未定义变量。

rules:规则等级设计

ESLint 规则有三个等级,对应不同的拦截策略:

等级 配置值 行为 用途
off 0 或 "off" 关闭规则 明确不检查
warn 1 或 "warn" 警告,不阻塞流程 建议性规范
error 2 或 "error" 错误,阻塞流程 硬性规范

配置中的四条规则各自代表了不同的质量管控意图:

javascript 复制代码
rules: {
  "no-var": 2,       // 禁止使用 var,必须用 let/const
  "no-console": 1,   // 不建议使用 console.log(开发调试用,上线后移除)
  "quotes": ["error", "double"],  // 字符串必须用双引号
  "semi": ["error", "always"],    // 语句末尾必须加分号
  "indent": ["error", 2],         // 缩进必须为 2 个空格
}

no-var: 2 是硬性规则。var 存在作用域提升和全局污染问题,ES6 之后 letconst 完全取代了 var。这条规则设为 error 级别,意味着团队中任何人的代码出现 var 都无法通过 ESLint 检查。

no-console: 1 是警告级别。开发阶段大量使用 console.log 是正常的,但上线前应该清理掉。设成 warn 而不是 error,让团队在开发时可以正常使用 console.log,但 eslint 检查时会给出警告提示,提醒开发者注意。

quotessemi 使用数组语法配置带参数的规则:["error", "double"] 表示规则等级为 error,双引号是具体的规则参数。"always" 表示必须加分号,"never" 表示禁止分号。

运行检查:pnpm lint

package.json 中定义了两个脚本:

json 复制代码
{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint --fix ."
  }
}

eslint . 对当前目录下所有匹配的文件执行检查。eslint --fix . 在检查的基础上自动修复可修复的规则(如 quotessemiindent 等格式化规则)。

index.mjs 执行 pnpm lint 后的输出:

javascript 复制代码
/path/to/index.mjs
  1:1  error    Unexpected var, use let or const instead  no-var
  1:5  warning  Unexpected console statement              no-console
  4:3  error    Expected indentation of 2 spaces but found 4  indent

每个错误都包含:行号列号、问题描述、违反的规则名。开发者不需要记住所有规则,ESLint 在输出中精确指出了每一条违规。

typescript-eslint:TypeScript 生态的扩展

tseslint.configs.recommended 集成了 TypeScript 的推荐规则预设,提供了针对 TypeScript 语法的检查能力------类型推断、未使用的变量、空值检查等。typescript-eslint 包包含了 TypeScript 解析器(@typescript-eslint/parser)和规则集(@typescript-eslint/eslint-plugin),通过预设配置一次性注入。

注意 tseslint.configs.recommended 是作为 defineConfig 数组的第二个元素传入的,与第一个配置块并列。这意味着 TypeScript 规则与自定义规则是平行关系,ESLint 会合并两者,遇到冲突时后面的配置优先。

ESLint 的工程化价值

ESLint 在工程化中的角色不仅仅是"代码检查"。它解决了三个核心问题:

风格统一。团队成员来自不同背景,有人习惯分号,有人不写分号;有人用单引号,有人用双引号。ESLint 用配置消除了这类无意义的争论------规则写死了,所有人都按同一套规范执行。

缺陷拦截no-var 防止了作用域提升带来的 bug,no-undef 捕获了未定义变量的引用,no-unused-vars 清理了遗留的废弃代码。ESLint 在代码进入代码审查之前就完成了第一轮质量筛选。

规范落地。规则三个等级的设计让规范落地有梯度------error 是硬性红线,warn 是柔性提醒,off 是明确放行。团队可以逐步收紧规则,而不是一次性强制执行全部规范。

总结

ESLint Flat Config 用 eslint.config.mjs 单一入口替代了传统的多层配置体系。defineConfig 接收配置数组,通过 files 匹配文件范围、globals 声明运行环境、rules 定义三个等级的规则,配合 typescript-eslint 扩展支持 TypeScript。

no-var: 2 禁止 var 声明,no-console: 1 提醒清理调试日志,quotessemiindent 统一代码风格。eslint --fix 自动修复可修正的格式问题。ESLint 的核心价值不在于检查本身,而在于将代码规范从"约定"转化为"强制"------让团队代码风格一致、可读性强、潜在 bug 在第一道防线就被拦截。

相关推荐
电子科技圈15 小时前
IAR与东软睿驰达成战略合作,强化软件开发效率与生态协作
设计模式·开源·软件工程·软件构建·代码规范·设计规范·代码复审
这个DBA有点耶2 天前
大事务的“事前预防”:监控、拦截、Kill,四层防线一次讲透
数据库·mysql·代码规范
沫璃染墨5 天前
《Qt从零入门系列(六):信号与槽进阶——从多种连接方式到Lambda表达式》
开发语言·c++·qt·代码规范·设计规范·qt5
嘟嘟07176 天前
SDD 规范驱动开发:从 vibe coding 崩盘到"两次创造"
设计模式·代码规范·vibecoding
JavaDog程序狗7 天前
【规范】这套 Git 规范,救了整个团队
git·代码规范·workflow
梦梦代码精8 天前
用开源BuildingAI打造C端AI助手,内置写作/绘画/长文/漫剧,商业化模块全预制
docker·ai·ai作画·开源·代码规范
小林ixn8 天前
TS 工具类型实战:Pick/Omit/Partial/Record 一次讲透,别再 Omit 反了
typescript·代码规范
慌途L10 天前
Open Code Review 详解:阿里巴巴开源 AI 代码审查工具
ai·ocr·代码规范·code review·ai代码审查