ESLint 是 JavaScript 和 TypeScript 领域最广泛使用的静态分析工具。它能识别有问题的代码模式、强制执行编码规范,并在代码进入生产环境之前发现 Bug。随着 ESLint 9 和全新扁平配置系统的发布,该工具经历了自创建以来最重大的架构变革。无论你是在编写小型脚本还是维护大型 Monorepo,ESLint 都能帮助团队在每个文件中编写一致、高质量的代码。
ESLint 9 引入了扁平配置(eslint.config.js)取代旧的 .eslintrc 格式。它提供原生 TypeScript-ESLint 支持、React/Vue/Angular 框架插件、自定义规则编写、可共享配置、自动修复功能和深度 IDE 集成。扁平配置使用 JavaScript 模块实现完全的编程控制,简化了配置合并,消除了令人困惑的 extends/overrides 级联。
- ESLint 9 扁平配置(eslint.config.js)用更简单、更可预测的基于 JavaScript 的配置系统取代了 .eslintrc。
- TypeScript-ESLint 提供类型感知的 Lint 规则,能捕获 TypeScript 编译器无法检测到的错误。
- ESLint 自动修复可以自动纠正许多问题,包括格式化、导入排序和代码风格违规。
- 框架插件(React、Vue、Angular)为 Hooks、模板语法和生命周期模式添加组件特定规则。
- 可共享配置让团队能够立即采用经过实战检验的规则集。
- ESLint 负责代码检查,Prettier 负责格式化。Biome 提供一体化方案但插件生态较小。
什么是 ESLint 9 和扁平配置?
ESLint 是一个可插拔的 JavaScript 和 TypeScript 静态分析工具,它将源代码解析为抽象语法树(AST),然后运行一组规则进行检查。ESLint 9 是当前的主要版本,引入了扁平配置作为默认配置格式。
扁平配置用单个 eslint.config.js 文件取代了旧的 .eslintrc 格式,导出一个配置对象数组。每个对象指定适用的文件、启用的规则和加载的插件。配置对象从上到下合并,使解析逻辑透明且可预测。
# Install ESLint 9
npm init @eslint/config@latest
# Or install manually
npm install --save-dev eslint @eslint/js
# This creates eslint.config.js (flat config)
# No more .eslintrc.json, .eslintrc.yml, or .eslintrc.jsESLint vs Prettier vs Biome
了解 ESLint 与 Prettier 和 Biome 的关系有助于为项目选择正确的工具组合。以下是它们核心能力的对比:
| 功能 | ESLint | Prettier | Biome |
|---|---|---|---|
| 代码质量规则 | 是(数百条) | 否 | 是(不断增长) |
| 代码格式化 | 有限(通过规则) | 是(固执己见) | 是(Prettier 兼容) |
| TypeScript 支持 | 通过 typescript-eslint | 内置解析 | 内置 |
| 自定义规则 | 是(庞大生态) | 否 | 有限 |
| 速度 | 中等 | 快 | 非常快(Rust) |
| 插件生态 | 最大 | 极少 | 小但在增长 |
| 框架插件 | React、Vue、Angular、Svelte | 不适用 | React(部分) |
2026 年最常见的配置是 ESLint 负责代码质量加上 Prettier 负责格式化。如果项目不依赖框架特定的 ESLint 插件,Biome 是一个优秀的一体化替代方案。
设置扁平配置(eslint.config.js)
扁平配置是 ESLint 9 中唯一支持的格式。配置文件导出一个配置对象数组。每个对象可以指定 files、ignores、plugins、rules、languageOptions 和 settings。
与旧格式不同,没有 extends 关键字。你将配置作为 JavaScript 模块导入并展开到数组中,消除了 .eslintrc 中令人困惑的 extends、overrides 和 env 级联。
// eslint.config.js - Basic flat config
import js from "@eslint/js";
export default [
// Global ignores (like .eslintignore)
{
ignores: ["dist/", "build/", "node_modules/", "*.min.js"],
},
// ESLint recommended rules for all JS files
js.configs.recommended,
// Custom overrides
{
files: ["**/*.js", "**/*.mjs"],
rules: {
"no-unused-vars": "warn",
"no-console": ["error", { allow: ["warn", "error"] }],
"prefer-const": "error",
"no-var": "error",
eqeqeq: ["error", "always"],
},
},
];规则和严重性级别
每条 ESLint 规则都有一个严重性级别来决定如何报告违规。理解这些级别对于有效配置项目至关重要。
- "off"(或 0)- 完全禁用规则。Lint 过程中不运行该规则。 - undefined
- "warn"(或 1)- 将违规报告为警告。Lint 过程成功退出。用于正在迁移的规则。 - undefined
- "error"(或 2)- 将违规报告为错误。Lint 过程以非零代码退出。用于必须强制执行的规则。 - undefined
规则还可以接受配置选项数组。第一个元素是严重性,后续元素是规则特定设置。
// Rule configuration examples
export default [
{
rules: {
// Severity only
"no-debugger": "error",
"no-alert": "warn",
"no-eval": "off",
// Severity + options
"no-unused-vars": ["error", {
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
}],
// Numeric severity (0=off, 1=warn, 2=error)
"no-console": [1, { allow: ["warn", "error", "info"] }],
// Complex options
"no-restricted-imports": ["error", {
patterns: [{
group: ["lodash"],
message: "Import from lodash-es instead for tree-shaking.",
}],
}],
},
},
];TypeScript-ESLint 集成
TypeScript-ESLint 是使 ESLint 能够检查 TypeScript 文件的官方工具。它提供 TypeScript 解析器、TypeScript 特定规则集和利用 TypeScript 编译器 API 进行更深层分析的类型感知规则。
类型感知规则是 TypeScript-ESLint 最强大的功能。它们使用完整的 TypeScript 类型系统检测 TypeScript 编译器和基本 Lint 规则无法捕获的问题。
// eslint.config.js - TypeScript-ESLint setup
import js from "@eslint/js";
import tseslint from "typescript-eslint";
export default tseslint.config(
js.configs.recommended,
// Recommended type-checked rules
...tseslint.configs.recommendedTypeChecked,
// Stylistic type-checked rules (optional)
...tseslint.configs.stylisticTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
// Custom TypeScript rules
{
files: ["**/*.ts", "**/*.tsx"],
rules: {
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/strict-boolean-expressions": "warn",
"@typescript-eslint/no-unnecessary-condition": "error",
"@typescript-eslint/prefer-nullish-coalescing": "error",
},
},
// Disable type-aware rules for JS files
{
files: ["**/*.js", "**/*.mjs"],
...tseslint.configs.disableTypeChecked,
},
);React、Vue 和 Angular 插件
ESLint 为每个主要前端框架都有专门的插件。这些插件添加了理解框架特定模式的规则。
React 和 JSX
eslint-plugin-react 和 eslint-plugin-react-hooks 包为 React 组件和 Hooks 提供规则。Hooks 插件强制执行 Hooks 规则,这对避免函数组件中的微妙 Bug 至关重要。
// eslint.config.js - React + Hooks
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
export default [
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ["**/*.tsx", "**/*.jsx"],
plugins: {
react,
"react-hooks": reactHooks,
},
languageOptions: {
parserOptions: {
ecmaFeatures: { jsx: true },
},
},
rules: {
...react.configs.recommended.rules,
...reactHooks.configs.recommended.rules,
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
"react-hooks/exhaustive-deps": "warn",
},
settings: {
react: { version: "detect" },
},
},
];Vue.js
eslint-plugin-vue 包为 Vue 单文件组件提供规则。它解析 template、script 和 style 部分并强制执行 Vue 特定约定。
// eslint.config.js - Vue 3
import js from "@eslint/js";
import vue from "eslint-plugin-vue";
import vueParser from "vue-eslint-parser";
import tseslint from "typescript-eslint";
export default [
js.configs.recommended,
...vue.configs["flat/recommended"],
{
files: ["**/*.vue"],
languageOptions: {
parser: vueParser,
parserOptions: {
parser: tseslint.parser,
sourceType: "module",
},
},
rules: {
"vue/multi-word-component-names": "warn",
"vue/no-unused-vars": "error",
"vue/require-default-prop": "error",
},
},
];Angular
@angular-eslint 包取代 TSLint 成为 Angular 项目的官方 Lint 解决方案。它们为组件装饰器、依赖注入、模板语法和生命周期钩子提供规则。
// eslint.config.js - Angular
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import angular from "angular-eslint";
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
...angular.configs.tsRecommended,
{
files: ["**/*.ts"],
rules: {
"@angular-eslint/directive-selector": ["error", {
type: "attribute",
prefix: "app",
style: "camelCase",
}],
"@angular-eslint/component-selector": ["error", {
type: "element",
prefix: "app",
style: "kebab-case",
}],
},
},
{
files: ["**/*.html"],
...angular.configs.templateRecommended,
...angular.configs.templateAccessibility,
},
);编写自定义规则
ESLint 规则是接收 AST 节点和上下文对象的函数。上下文提供报告问题和访问设置的方法。自定义规则让你可以强制执行现有规则未涵盖的项目特定约定。
每条规则导出一个 meta 对象和一个 create 函数,create 返回一个将 AST 节点类型映射到处理函数的对象。
// eslint-plugin-custom/no-hardcoded-colors.js
export default {
meta: {
type: "suggestion",
docs: {
description: "Disallow hardcoded color hex values",
},
messages: {
noHardcodedColor:
"Avoid hardcoded color '{{ value }}'. Use a design token instead.",
},
schema: [],
},
create(context) {
const HEX_PATTERN = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\$/;
return {
Literal(node) {
if (
typeof node.value === "string" &&
HEX_PATTERN.test(node.value)
) {
context.report({
node,
messageId: "noHardcodedColor",
data: { value: node.value },
});
}
},
};
},
};
// Using the custom rule in eslint.config.js
import noHardcodedColors from "./eslint-plugin-custom/no-hardcoded-colors.js";
export default [
{
plugins: {
custom: { rules: { "no-hardcoded-colors": noHardcodedColors } },
},
rules: {
"custom/no-hardcoded-colors": "warn",
},
},
];可共享配置
可共享配置是导出 ESLint 配置数组的 npm 包。它们让团队无需手动配置数百条规则就能采用精选的规则集。
2026 年流行的可共享配置包括 @eslint/js、typescript-eslint 配置、@antfu/eslint-config 和 eslint-config-airbnb。
// eslint.config.js - Using @antfu/eslint-config
import antfu from "@antfu/eslint-config";
export default antfu({
// Frameworks: auto-detected or manually enabled
typescript: true,
react: true,
vue: false,
// Formatting with Prettier-compatible style
stylistic: {
indent: 2,
quotes: "single",
semi: false,
},
// Override specific rules
rules: {
"no-console": "warn",
},
});
// eslint.config.js - Composing multiple configs
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import prettierConfig from "eslint-config-prettier";
export default [
js.configs.recommended,
...tseslint.configs.strict,
prettierConfig, // Must be last to override formatting rules
];忽略文件和目录
在扁平配置中,使用配置对象的 ignores 属性来忽略文件。仅包含 ignores 的配置对象充当全局忽略模式,类似于旧的 .eslintignore 文件。
// eslint.config.js - Ignoring patterns
export default [
// Global ignores (standalone object = .eslintignore equivalent)
{
ignores: [
"dist/",
"build/",
"coverage/",
"node_modules/",
"*.min.js",
"**/*.generated.ts",
".next/",
"public/",
],
},
// Scoped ignores: exclude test fixtures from strict rules
{
files: ["**/*.ts"],
ignores: ["**/__fixtures__/**", "**/__mocks__/**"],
rules: {
"@typescript-eslint/no-explicit-any": "error",
},
},
];CLI 使用和常用命令
ESLint CLI 提供用于检查、修复、缓存和调试配置的命令。以下是日常开发中最常用的命令和标志。
# Lint all files in the project
npx eslint .
# Lint specific files or directories
npx eslint src/ tests/
npx eslint "src/**/*.{ts,tsx}"
# Auto-fix all fixable issues
npx eslint . --fix
# Enable caching for faster re-runs
npx eslint . --cache --cache-location .eslintcache
# Fail on warnings (useful in CI)
npx eslint . --max-warnings 0
# Show which config applies to a file
npx eslint --inspect-config
# Print timing info for rules (find slow rules)
TIMING=1 npx eslint .
# Output results as JSON
npx eslint . --format json --output-file report.json
# Common package.json scripts
# "lint": "eslint ."
# "lint:fix": "eslint . --fix"
# "lint:ci": "eslint . --cache --max-warnings 0"IDE 集成(VS Code)
ESLint VS Code 扩展在你输入时提供实时 Lint 反馈。它内联显示错误和警告,提供快速修复操作,并可在保存时自动修复。
将以下设置添加到 VS Code settings.json 中,以获得 ESLint 保存时自动修复和 Prettier 格式化的最佳体验。
// .vscode/settings.json
{
// Enable ESLint for these languages
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue"
],
// Auto-fix ESLint issues on save
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
// Use Prettier as the default formatter
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
// ESLint uses flat config by default in v9
// No additional setting needed for eslint.config.js
}自动修复和格式化
ESLint 可以使用 --fix 标志自动修复许多规则违规。可修复的规则包括导入排序、未使用的禁用指令、间距问题和代码风格模式。
将 ESLint 与 Prettier 配合使用时,配置 eslint-config-prettier 关闭与 Prettier 格式化冲突的 ESLint 规则。
# Install Prettier + ESLint integration
npm install --save-dev prettier eslint-config-prettier
# eslint.config.js
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import prettierConfig from "eslint-config-prettier";
export default [
js.configs.recommended,
...tseslint.configs.recommended,
// prettier must be LAST to turn off conflicting rules
prettierConfig,
];
# CI pipeline: run both
# Step 1: Check formatting
# npx prettier --check .
# Step 2: Check code quality
# npx eslint . --max-warnings 0从 .eslintrc 迁移到扁平配置
ESLint 提供迁移工具和兼容性工具帮助团队从旧的 .eslintrc 格式过渡到扁平配置。@eslint/eslintrc 包提供 FlatCompat 类来包装旧配置。
要进行干净的迁移,先运行 ESLint 配置迁移工具,然后逐步将 FlatCompat 包装器替换为原生扁平配置。
# Step 1: Run the migration tool
npx @eslint/migrate-config .eslintrc.json
# This generates eslint.config.mjs with FlatCompat wrappers
# for any legacy plugins that do not support flat config yet.
# Step 2: Example generated config with FlatCompat
# import { FlatCompat } from "@eslint/eslintrc";
# import path from "node:path";
# import { fileURLToPath } from "node:url";
#
# const __filename = fileURLToPath(import.meta.url);
# const __dirname = path.dirname(__filename);
# const compat = new FlatCompat({ baseDirectory: __dirname });
#
# export default [
# ...compat.extends("eslint-config-airbnb"),
# { rules: { "no-console": "warn" } },
# ];
# Step 3: Gradually replace FlatCompat with native imports
# as plugins release flat-config-compatible versions.
# Delete .eslintrc.json and .eslintignore when done.Monorepo 配置
在 Monorepo 中,通常有一个定义共享规则的根 eslint.config.js,加上包特定的覆盖。扁平配置使这变得简单,因为你可以从不同包导入和组合配置数组。
每个工作区包可以导出自己的配置片段,根配置导入并合并它们。
// eslint.config.js - Monorepo root config
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
export default [
// Global ignores
{ ignores: ["**/dist/", "**/node_modules/", "**/.next/"] },
// Shared base rules for all packages
js.configs.recommended,
...tseslint.configs.recommended,
// Frontend: React rules
{
files: ["packages/web/**/*.tsx", "packages/web/**/*.ts"],
plugins: { react, "react-hooks": reactHooks },
rules: {
...react.configs.recommended.rules,
...reactHooks.configs.recommended.rules,
"react/react-in-jsx-scope": "off",
},
settings: { react: { version: "detect" } },
},
// Backend: Node.js rules
{
files: ["packages/api/**/*.ts"],
rules: {
"no-console": "off",
},
},
// Tests: relaxed rules
{
files: ["**/*.test.ts", "**/*.spec.ts"],
rules: {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
},
},
];性能优化
ESLint 在大型代码库上可能较慢,尤其是使用类型感知 TypeScript 规则时。以下技术可以显著减少 Lint 时间。
- 启用 --cache 标志跳过未更改文件的重新检查。
- 使用 typescript-eslint 的项目引用限制 Monorepo 中每个包的类型检查范围。
- 使用全局 ignores 排除生成的文件、构建输出和 node_modules。
- 如果性能成本大于收益,对测试文件禁用类型感知规则。
- 使用 eslint-plugin-import 并启用解析器缓存。
- 使用 turbo lint 或 nx lint 等工具跨工作区并行运行 ESLint。
- 固定特定规则集而非使用启用所有规则的 "all" 配置。
- 使用 TIMING=1 npx eslint 分析慢规则。
最佳实践
遵循以下建议从 ESLint 中获得最大价值。
- 从推荐配置开始定制,而不是从头构建。
- 将 ESLint 错误视为 CI 阻断器。警告应该是临时的。
- ESLint 负责代码质量,Prettier 负责格式化。配置 Prettier 时不要使用 ESLint 格式化规则。
- 用注释组织扁平配置文件,分隔基础规则、TypeScript 规则、框架规则和测试覆盖。
- 固定 ESLint 和插件版本。主版本升级可能改变规则行为。
- 谨慎使用 eslint-disable 注释。每条都应包含解释原因。
- 配置编辑器保存时自动修复,立即捕获问题。
- 在 CI 管道中使用 --max-warnings 0 防止警告积累。
- 每次主要版本发布时审查新规则。
- 在项目文档中记录自定义规则或非显而易见的配置选择。
常见问题
什么是 ESLint 扁平配置?
扁平配置是 ESLint 9 引入的新配置格式。它使用单个 eslint.config.js 文件导出配置对象数组。配置从上到下合并,取代了旧 .eslintrc 格式复杂的 extends/overrides 级联。
如何将 ESLint 与 TypeScript 一起使用?
安装 typescript-eslint 并在 eslint.config.js 中配置。使用 tseslint.config() 辅助函数提供推荐和严格规则预设。类型感知规则使用 TypeScript 编译器 API 进行更深层分析。
应该使用 ESLint 还是 Prettier?
两者都用。ESLint 处理代码质量规则,Prettier 处理格式化。安装 eslint-config-prettier 禁用冲突的规则。
如何从 .eslintrc 迁移到扁平配置?
运行 npx @eslint/migrate-config .eslintrc.json 生成扁平配置文件。逐步将 FlatCompat 包装器替换为原生扁平配置导入。
ESLint 和 Biome 有什么区别?
ESLint 是基于 JavaScript 的 Lint 工具,拥有最大的插件生态。Biome 是基于 Rust 的工具链,将 Lint 和格式化合二为一。Biome 更快但规则更少,框架插件支持有限。
如何自动修复 ESLint 错误?
运行 eslint --fix 自动修复所有可修复的违规。在 VS Code 中启用保存时自动修复。并非所有规则都可自动修复。
如何为 Monorepo 配置 ESLint?
在根目录放置 eslint.config.js 定义共享规则,使用 files 属性为特定包应用覆盖。Turborepo 和 Nx 可以跨工作区并行运行 ESLint。
如何提升 ESLint 性能?
启用 --cache 缓存,排除生成文件,限制类型感知规则范围,使用 TIMING=1 分析慢规则。在 Monorepo 中使用项目引用限制类型检查范围。