ESLint v9 配置详解:Flat Config 完全指南

672 阅读7分钟

一、核心概念与架构变化

1.1 配置系统重构

  • 单一配置文件eslint.config.js 替代传统的 .eslintrc.* 文件
  • 扁平结构:配置定义为数组,每个元素是一个独立配置对象
  • 显式文件匹配:每个配置块必须使用 files 属性指定目标文件
  • 无继承机制:不再向上级目录查找配置文件,避免意外继承

1.2 模块化设计

  • ESM 规范:配置文件必须使用 ESM 语法 (import/export)
  • 显式依赖:所有依赖(插件、预设、全局变量)需显式导入
  • 组合式配置:通过导入和展开共享配置实现复用

eslint.png

二、配置文件详解

2.1 基本结构

// eslint.config.js
import js from '@eslint/js';         // ESLint 核心规则
import globals from 'globals';       // 全局变量库
import tsParser from '@typescript-eslint/parser'; // TS解析器
import tsPlugin from '@typescript-eslint/eslint-plugin'; // TS插件export default [
  // 全局忽略配置(必须放在第一个)
  {
    ignores: ['dist/**', 'coverage/**', '**/*.config.js']
  },
  
  // JavaScript 基础配置
  {
    files: ['**/*.js'],
    ...js.configs.recommended,  // 使用推荐规则
    languageOptions: {
      globals: {
        ...globals.browser,     // 浏览器全局变量
        ...globals.node         // Node.js 全局变量
      },
      parserOptions: {
        ecmaVersion: 'latest',  // 最新ECMAScript特性
        sourceType: 'module'    // 模块化语法
      }
    },
    rules: {
      'no-console': 'warn',     // 自定义规则
      'quotes': ['error', 'single']
    }
  },
  
  // TypeScript 配置
  {
    files: ['**/*.ts'],
    plugins: {
      '@typescript-eslint': tsPlugin  // 注册TS插件
    },
    languageOptions: {
      parser: tsParser,          // 指定TS解析器
      parserOptions: {
        project: './tsconfig.json'  // TS项目配置
      }
    },
    rules: {
      '@typescript-eslint/no-explicit-any': 'error'
    }
  },
  
  // 测试文件特殊配置
  {
    files: ['**/*.test.js'],
    languageOptions: {
      globals: {
        ...globals.jest         // Jest测试框架全局变量
      }
    },
    rules: {
      'no-unused-expressions': 'off'
    }
  }
];

2.2 配置对象属性详解

1. files (必需)

  • 指定配置适用的文件模式

  • 使用 minimatch 格式的 glob 模式

  • 示例:

    files: ['src/**/*.js'],        // src目录下所有JS文件
    files: ['**/*.tsx'],           // 所有TSX文件
    files: ['*.config.js'],        // 根目录下的配置文件
    

2. ignores (全局)

  • 替代 .eslintignore 功能

  • 必须在数组的第一个配置对象中定义

  • 示例:

    ignores: [
      '**/node_modules/**',  // 忽略node_modules
      'dist/**',             // 忽略dist目录
      '*.d.ts'               // 忽略类型声明文件
    ]
    

3. languageOptions (核心)

替代原 env, parser, parserOptions 等功能

属性类型说明示例
globalsObject全局变量定义{ ...globals.browser, myGlobal: true }
parserObject自定义解析器parser: tsParser
parserOptionsObject解析器配置{ ecmaVersion: 2022, sourceType: 'module' }
sourceTypeString脚本类型'script''module'

4. plugins (插件系统)

  • 使用对象格式注册插件
  • 键名作为插件前缀(用于规则名)
  • 值必须是导入的插件对象
import reactPlugin from 'eslint-plugin-react';
​
plugins: {
  react: reactPlugin,      // 使用时前缀为 'react/'
  '@typescript-eslint': tsPlugin // 前缀为 '@typescript-eslint/'
}

5. rules (规则配置)

  • 格式:'规则名': [错误级别, 配置选项]
  • 错误级别:'error', 'warn', 'off'0, 1, 2
  • 插件规则格式:'插件名/规则名'
rules: {
  // 核心规则
  'semi': ['error', 'always'],
  
  // 插件规则
  'react/jsx-uses-react': 'error',
  '@typescript-eslint/no-unused-vars': 'warn',
  
  // 禁用规则
  'no-debugger': 'off'
}

6. settings (共享配置)

  • 在插件间共享的配置对象
  • 常用于框架版本检测等场景
settings: {
  react: {
    version: 'detect'  // 自动检测React版本
  }
}

7. linterOptions (Linter配置)

  • 控制ESLint核心行为

  • 目前支持:

    linterOptions: {
      reportUnusedDisableDirectives: true // 报告未使用的禁用指令
    }
    

三、关键功能实现

3.1 使用预设配置

替代原 extends 功能,通过导入和展开实现

import js from '@eslint/js';
import airbnb from 'eslint-config-airbnb';
​
export default [
  {
    files: ['**/*.js'],
    ...js.configs.recommended,       // ESLint推荐规则
    ...airbnb,                      // Airbnb风格指南
    rules: {
      // 覆盖预设规则
      'import/prefer-default-export': 'off'
    }
  }
];

3.2 处理器配置

处理非JavaScript文件(如Markdown、Vue)

import markdown from 'eslint-plugin-markdown';
​
export default [
  {
    files: ['**/*.md'],
    plugins: {
      markdown
    },
    processor: 'markdown/markdown'  // 指定处理器
  }
];

3.3 全局变量管理

使用 globals 包替代原 env 功能

import globals from 'globals';
​
export default [
  {
    files: ['**/*.js'],
    languageOptions: {
      globals: {
        ...globals.browser,   // 浏览器环境
        ...globals.node,      // Node.js环境
        MY_GLOBAL: 'readonly' // 自定义全局变量
      }
    }
  }
];

3.4 覆盖特定文件配置

使用多个配置块实现精细控制

export default [
  // 基础配置
  {
    files: ['**/*.js'],
    rules: {
      'no-console': 'error'
    }
  },
  
  // 覆盖测试文件配置
  {
    files: ['**/*.test.js'],
    rules: {
      'no-console': 'off',       // 允许测试中使用console
      'no-undef': 'off'          // 允许未定义变量
    }
  },
  
  // 配置文件特殊规则
  {
    files: ['*.config.js'],
    languageOptions: {
      sourceType: 'script'       // 使用脚本模式
    }
  }
];

四、高级配置技巧

4.1 动态配置生成

利用JavaScript能力创建动态配置

const isProduction = process.env.NODE_ENV === 'production';
​
export default [
  {
    files: ['src/**/*.js'],
    rules: {
      'no-debugger': isProduction ? 'error' : 'warn',
      'no-console': isProduction ? 'error' : 'off'
    }
  }
];

4.2 配置复用与共享

创建可复用配置模块

// eslint-config-custom/index.js
import globals from 'globals';
​
export const baseConfig = {
  languageOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    globals: { ...globals.node }
  },
  rules: {
    'no-console': 'warn',
    'semi': ['error', 'always']
  }
};
​
export const reactConfig = {
  plugins: { react },
  languageOptions: {
    parserOptions: {
      ecmaFeatures: { jsx: true }
    }
  },
  rules: {
    'react/prop-types': 'off'
  }
};

使用自定义配置:

import { baseConfig, reactConfig } from 'eslint-config-custom';
​
export default [
  {
    files: ['**/*.js'],
    ...baseConfig
  },
  {
    files: ['**/*.jsx'],
    ...baseConfig,
    ...reactConfig
  }
];

4.3 与Prettier集成

使用 eslint-config-prettier 避免冲突

import prettier from 'eslint-config-prettier';
​
export default [
  {
    files: ['**/*.{js,ts}'],
    // 其他配置...
  },
  prettier // 必须放在最后
];

五、迁移指南

5.1 迁移步骤

  1. 重命名配置文件:.eslintrc.jseslint.config.js
  2. 转换模块语法:module.exportsexport default
  3. 安装必要依赖:npm install globals @eslint/js
  4. 替换 envglobals 导入
  5. 拆分单一配置为多个配置块
  6. 为每个配置块添加 files 属性
  7. 转换插件注册方式:数组 → 对象格式
  8. 替换 extends 为配置导入展开
  9. 将忽略规则移至顶层 ignores
  10. 测试验证配置效果

5.2 自动迁移工具

# 1. 安装迁移工具
npm install -g @eslint/config-inspector
​
# 2. 转换配置文件
npx @eslint/config-inspector --fix
​
# 3. 可视化检查配置
npx @eslint/config-inspector

5.3 常见问题解决

  1. 解析器找不到问题

    // 错误:parser: '@typescript-eslint/parser'
    // 正确:
    import tsParser from '@typescript-eslint/parser';
    // ...
    languageOptions: { parser: tsParser }
    
  2. 插件规则不生效

    // 错误:plugins: ['react']
    // 正确:
    import reactPlugin from 'eslint-plugin-react';
    plugins: { react: reactPlugin }
    rules: { 'react/prop-types': 'off' }
    
  3. 全局变量未定义

    // 错误:env: { browser: true }
    // 正确:
    import globals from 'globals';
    languageOptions: { globals: { ...globals.browser } }
    

六、最佳实践

6.1 配置组织建议

export default [
  // 1. 全局忽略
  { ignores: [...] },
  
  // 2. 基础配置(所有文件)
  { 
    files: ['**/*.{js,ts}'],
    // 公共规则...
  },
  
  // 3. JavaScript配置
  {
    files: ['**/*.js'],
    // JS特定规则...
  },
  
  // 4. TypeScript配置
  {
    files: ['**/*.ts'],
    // TS特定规则...
  },
  
  // 5. 框架配置 (React/Vue等)
  {
    files: ['**/*.tsx'],
    // 框架规则...
  },
  
  // 6. 测试文件配置
  {
    files: ['**/*.test.{js,ts}'],
    // 测试规则...
  },
  
  // 7. 配置文件特殊规则
  {
    files: ['*.config.js'],
    // 配置规则...
  },
  
  // 8. 格式化工具集成 (Prettier)
  prettierConfig
];

6.2 性能优化

  1. 精确文件匹配:避免使用过于宽泛的 **/* 模式

  2. 限制TS类型检查范围

    // 仅对需要类型检查的文件启用
    {
      files: ['src/**/*.ts'],
      languageOptions: {
        parserOptions: {
          project: './tsconfig.json'
        }
      }
    }
    
  3. 按需加载配置:动态导入大型配置

    export default [
      {
        files: ['**/*.js'],
        ...(await import('large-config')).default
      }
    ];
    

七、完整配置示例

7.1 企业级React+TypeScript配置

// eslint.config.js
import js from '@eslint/js';
import globals from 'globals';
import tsParser from '@typescript-eslint/parser';
import tsPlugin from '@typescript-eslint/eslint-plugin';
import reactPlugin from 'eslint-plugin-react';
import reactHooksPlugin from 'eslint-plugin-react-hooks';
import jsxA11yPlugin from 'eslint-plugin-jsx-a11y';
import importPlugin from 'eslint-plugin-import';
import prettier from 'eslint-config-prettier';
​
// 自定义规则集
const customRules = {
  'no-console': ['warn', { allow: ['warn', 'error'] }],
  'react/react-in-jsx-scope': 'off',
  'react/prop-types': 'off',
  '@typescript-eslint/explicit-module-boundary-types': 'off',
  'import/order': [
    'error',
    {
      groups: [
        'builtin',
        'external',
        'internal',
        'parent',
        'sibling',
        'index'
      ],
      'newlines-between': 'always'
    }
  ]
};
​
export default [
  // 全局忽略
  {
    ignores: [
      '**/node_modules/**',
      'dist/**',
      'build/**',
      'coverage/**',
      '*.d.ts',
      '**/.next/**'
    ]
  },
​
  // 基础配置
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    ...js.configs.recommended,
    plugins: {
      import: importPlugin
    },
    languageOptions: {
      globals: {
        ...globals.browser,
        ...globals.es2021
      },
      parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module',
        ecmaFeatures: {
          jsx: true
        }
      }
    },
    rules: {
      ...customRules,
      'import/no-unresolved': 'error'
    }
  },
​
  // TypeScript配置
  {
    files: ['**/*.{ts,tsx}'],
    plugins: {
      '@typescript-eslint': tsPlugin
    },
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        project: './tsconfig.json',
        tsconfigRootDir: import.meta.dirname
      }
    },
    rules: {
      '@typescript-eslint/consistent-type-imports': 'error',
      '@typescript-eslint/no-floating-promises': 'error'
    }
  },
​
  // React配置
  {
    files: ['**/*.{jsx,tsx}'],
    plugins: {
      react: reactPlugin,
      'react-hooks': reactHooksPlugin,
      'jsx-a11y': jsxA11yPlugin
    },
    settings: {
      react: {
        version: 'detect'
      }
    },
    rules: {
      'react/jsx-uses-react': 'error',
      'react/jsx-uses-vars': 'error',
      'react-hooks/rules-of-hooks': 'error',
      'react-hooks/exhaustive-deps': 'warn',
      'jsx-a11y/alt-text': 'warn'
    }
  },
​
  // 测试文件配置
  {
    files: ['**/*.test.{js,ts,jsx,tsx}'],
    languageOptions: {
      globals: {
        ...globals.jest
      }
    },
    rules: {
      'no-unused-expressions': 'off',
      '@typescript-eslint/no-non-null-assertion': 'off'
    }
  },
​
  // Prettier集成(必须最后)
  prettier
];

八、调试与验证

8.1 CLI调试命令

# 检查特定文件
npx eslint src/index.js
​
# 输出使用的配置
npx eslint --print-config src/index.js > eslint_config.json
​
# 修复可自动修复的问题
npx eslint --fix src/
​
# 仅检查变更文件 (git)
npx eslint $(git diff --name-only HEAD)

8.2 IDE集成

  1. VS Code

    // .vscode/settings.json
    {
      "eslint.experimental.useFlatConfig": true,
      "eslint.validate": [
        "javascript",
        "typescript",
        "javascriptreact",
        "typescriptreact"
      ]
    }
    
  2. WebStorm:2023.3+ 版本原生支持 Flat Config

九、资源参考

  1. 官方迁移指南
  2. Flat Config文档
  3. 预定义配置集合
  4. 插件开发指南
  5. globals包文档

通过这份全面指南,您应该能够掌握ESLint v9的所有配置细节,并能够创建高效、可维护的代码质量检查配置。