eslint 插件
· 阅读需 23 分钟
现在才发现有时候真的是“磨刀不误砍柴工”,构建良好的工具可以辅助快速的开发。
之前比较忽略 eslint 插件的使用,现在发现还不错。是我肤浅了。
- 按需安装 : 避免堆砌插件,根据项目类型和痛点选择(例如:React 项目必装 eslint-plugin-react+ eslint-plugin-react-hooks)
- 组合配置 :多数插件提供预设配置(如 eslint-plugin-react/configs/recommended),直接继承减少手动配置
- 版本兼容 :注意插件与 ESLint 版本的兼容性(参考插件文档的 peerDependencies)
按需启用
- 不要盲目安装太多插件,否则配置复杂且 lint 速度变慢
- 所有插件在 Flat Config (
eslint.config.js) 中都应使用其.configs导出(如果支持),以获得最佳兼容性
一、常用插件
@eslint/js适用于 js 的通用配置eslint.config.mjs 片段import js from '@eslint/js'; // 必须:核心推荐规则
export default [
// 基础配置(所有文件通用)
js.configs.recommended, // 必须:ESLint 核心推荐规则
// ... 其他规则
];eslint-plugin-jsdocJSDoc 对 ESLint 的 linting 规则eslint.config.mjs 片段import jsdocPlugin from 'eslint-plugin-jsdoc'; // 可选:JSDoc 注释
export default [
// ... 其他规则
// 5.1 可选:JSDoc 注释规范
{
files: ['**/*.{js,ts,jsx,tsx}'],
plugins: { jsdoc: jsdocPlugin },
rules: {
// 基础规则
'jsdoc/check-alignment': 'error',
'jsdoc/check-param-names': 'error',
'jsdoc/check-tag-names': [
'error',
{
// 配置允许的标签
definedTags: ['packageDocumentation'],
},
],
'jsdoc/check-types': 'error',
// TypeScript 适配规则
'jsdoc/no-types': 'error',
'jsdoc/require-param-type': 'off', // 使用 TS 类型
'jsdoc/require-returns-type': 'off', // 使用 TS 类型
// 文档质量规则
'jsdoc/require-description': [
'error',
{
contexts: ['TSInterfaceDeclaration', 'TSTypeAliasDeclaration'],
},
],
'jsdoc/require-jsdoc': [
'warn',
{
require: {
FunctionDeclaration: true,
MethodDefinition: true,
ClassDeclaration: true,
},
},
],
},
},
// ... 其他规则
];eslint-config-prettier关闭所有不必要的规则或可能与Prettier冲突的规则eslint.config.mjs 片段import prettierConfig from 'eslint-config-prettier'; // 必须:关闭 Prettier 冲突规则
export default [
// ... 其他规则
// 关闭 Prettier 冲突规则(必须,用 Prettier 时)
prettierConfig, // 必须放在最后
];typescript-eslint工具可以让你在 ESLint 上使用 TypeScripteslint.config.mjs 片段import tseslint from 'typescript-eslint'; // 必须:TypeScript 支持
export default [
// ... 其他规则
// TypeScript 配置(必须)
...tseslint.configs.recommended.map(config => ({
...config,
files: ['src/**/*.{ts,tsx}'],
languageOptions: {
...config.languageOptions,
globals: {
...globals.browser,
...globals.node,
...globals.es2025, // 浏览器 + Node + ES2025 全局
},
parserOptions: {
...config.languageOptions?.parserOptions,
tsconfigRootDir: import.meta.dirname, // ESM 获取当前配置目录
project: true, // 类型感知规则,或者指定实际的 tsconfig.json
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: { jsx: true }, // 开启JSX解析,适配React
},
},
rules: {
// TS 核心规则(示例)
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_' },
],
'@typescript-eslint/prefer-nullish-coalescing': 'error',
},
})),
// ... 其他规则
];- react 用:
- next.js 用
- angular 用
- vue 用
eslint-plugin-vueVue 单文件组件( SFC )规则(模版语法、 Composition API 、 选项式 API )
- Nuxt 用
eslint-plugin-nuxtNuxt 专用规则(页面/组件结构、中间件、 SEO )
二、代码质量与最佳实践
提升代码健壮性、可读性和现代 JS/TS 实践的工具。
eslint-plugin-promisePromise 规范(错误捕获、链式调用、async/await 最佳实践),用于 异步代码较多的项目eslint-plugin-sonarjsSonarQube 代码质量检测(重复代码、复杂逻辑、潜在 Bug),用于 企业级项目(代码审计)eslint-plugin-optimize-regex正则表达式性能优化(避免回溯陷阱),用于 大量使用正则的项目eslint-plugin-unicorn现代 JS/TS 最佳实践(空白值处理、性能优化、错误处理),用于 所有 JS/TS 项目eslint-plugin-no-use-extend-native禁止扩展原生对象(如 Array.prototype),用于 避免污染全局环境eslint-plugin-functional函数式编程规范(纯函数、不可变数据、避免副作用),用于 函数式编程风格项目
三、导入与模块管理
处理模块导入/导出的规范性(排序、路径别名、循环依赖等)。
eslint-plugin-import导入导出规范(排序、路径别名校验、禁止循环依赖、Node.js 模块解析),用于 所有模块化项目(必装)eslint-plugin-simple-import-sort简化导入分组排序(自动按类型分组:内置模块、第三方、本地),用于 替代 import/order的轻量方案eslint-plugin-alias路径别名校验(如 @/components是否指向正确目录),用于 使用 Webpack/Vite 别名配置的项目eslint-plugin-unused-imports自动修复 未使用的 imports (尤其是适合 TS 项目,因为 TS 默认不报unused import)
四、测试框架专用插件
针对测试代码的规则集,确保测试用例质量。
eslint-plugin-jestJest 测试规则(用例命名、断言规范、Mock 函数使用),用于 Jest 单元测试项目eslint-plugin-mochaMocha 测试规则(钩子函数使用、异步测试规范),用于 Mocha + Chai 测试项目eslint-plugin-cypressCypress 端到端测试规则(命令链、元素定位最佳实践),用于 Cypress E2E 测试项目eslint-plugin-testing-libraryTesting Library 规则(优先用 DOM 查询而非 test-id),用于 ** React/Vue 组件测试(Testing Library)**
五、安全与隐私保护
检测代码中的安全风险(如硬编码密钥、XSS 漏洞)。
eslint-plugin-security常见安全漏洞(XSS、SQL 注入、不安全的加密算法),用于 处理用户输入或后端交互的项目eslint-plugin-no-secrets禁止提交敏感信息(API 密钥、密码、令牌),用于 ** 所有开源/协作项目(防泄露)**eslint-plugin-csp内容安全策略(CSP)违规检测(如不安全的内联脚本),用于 注重安全的 Web 项目
六、样式与格式(非 Prettier)
补充代码风格规则(与 Prettier 分工:Prettier 管格式,插件管逻辑风格)。
eslint-plugin-airbnb-baseAirbnb 基础规则(不含 React ,聚焦 JS 最佳实践),用于 喜欢 Airbnb 风格的非 React 项目eslint-plugin-airbnbAirbnb 完整规则(含 React ) ,用于 ** Airbnb 风格 React 项目**eslint-plugin-standardStandard 风格(无分号、单引号、缩进 2 空格),用于 遵循 Standard 规范的项目eslint-plugin-superic严格的代码风格(强制类型注解、禁止隐式转换),用于 强类型偏好项目
七、特定文件类型支持
处理非 JS/TS 文件的 ESLint 校验(如 JSON、Markdown、HTML)。
eslint-plugin-jsonc校验 JSON/JSONC(带注释的 JSON)文件,用于 配置文件(tsconfig.json、package.json)eslint-plugin-yaml校验 YAML 文件(如 GitHub Actions、Docker Compose),用于 DevOps 配置文件eslint-plugin-html校验 HTML 中的内联 JS 代码,用于 传统 HTML 项目(含<script>标签)eslint-plugin-markdown校验 Markdown 中的代码块(JS/TS/React 等),用于 技术文档(含代码示例)eslint-plugin-toml校验 TOML 文件(如 Rust Cargo.toml、Python pyproject.toml),用于 多语言项目配置
八、Node.js 与环境适配
针对 Node.js 运行时或特定环境的规则。
eslint-plugin-nodeNode.js 环境规则(模块导入、全局变量、process 使用),用于 Node.js 后端项目eslint-plugin-compat浏览器兼容性检查(基于 caniuse 数据),用于 跨浏览器 Web 项目eslint-plugin-eslint-comments校验 ESLint 注释(如/* eslint-disable */的滥用),用于 规范 ESLint 注释使用
eslint-plugin-node 已不再维护现在由 eslint-plugin-n 从 eslint-plugin-node v1.1.0 分支而来
九、正则与表达式
专门优化正则表达式的规则。
eslint-plugin-regexp正则表达式语法校验、性能优化(避免灾难性回溯)、可读性提升,用于 大量使用正则的项目(如表单验证)
十、实用小工具插件
解决特定痛点的轻量插件。
eslint-plugin-enforce-module-boundaries模块边界检查(禁止跨层引用,如 UI 组件直接调用 API 层),用于 分层架构项目(DDD、Clean Architecture)eslint-plugin-boundaries强制模块边界(如/api不能直接调用/ui),适用于 大型 Monorepo 架构eslint-plugin-deprecation标记已弃用的 API 使用(结合 JSDoc @deprecated),维护老项目或迭代频繁的代码库eslint-plugin-perfectionist自动排序一切可排序的代码,比如:对象的 Key、数组项、导入语句、接口的属性、枚举值、甚至是 CSS 类名,支持 TS/JS/JSON/Vue/React ,规则及其灵活。适用于 强迫症晚期患者
十一、触发模式
在 VSCode 中(因为我用的是 VsCode ,别的没用过)使用 ESLint 时, 自动修复(保存时应用) 和 手动执行 eslint --fix 是两种不同的触发模式 ,具体取决于 VSCode 设置和 ESLint 规则的支持情况。
1. 默认行为
VSCode 不会自动修复 ESLint 错误,需手动执行 eslint --fix 或在 VSCode 中配置 **保存时自动触发修复。自动修复触发条件:
- VSCode 安装了 ESLint 扩展
- 在 VSCode 中设置启用 「保存时自动修复规则」(通过
editor.codeActionsOnSave设置) - ESLint 规则本身支持
--fix(大部分规则支持,少数需要手动修复)
2. 配置 VSCode 保存时自动修复 ESLint
- 安装 VSCode ESLint 扩展
- 配置 VSCode 自动修复
.vscode/setting.json(工作区配置,优先推荐)
{
// 保存时自动修复 ESLint 可修复的问题
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true // ✅ 核心配置:保存时触发 ESLint 修复
},
// 确保 ESLint 处理 TypeScript/JSX 文件
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
// 可选:禁用 Vetur/Volar 的内置格式化(避免与 ESLint 冲突)
"vetur.format.defaultFormatter.js": "none",
"volar.formatting.enabled": false,
// 可选:与 Prettier 配合(若使用 Prettier 格式化)
"prettier.enable": true,
"eslint.format.enable": false, // 禁用 ESLint 格式化,交给 Prettier
"editor.defaultFormatter": "esbenp.prettier-vscode" // 默认用 Prettier 格式化
} - 原理说明 :
source.fixAll.eslint: true: 告诉 VSCode 在保存文件时,自动对可修复的 ESLint 错误执行eslint --fixeslint.validate: 指定 ESLint 需要处理的文件类型(确保 TS/TSX/JS/JSX 被覆盖)
3. 手动执行 eslint --fix (备用方案)
如果不想配置自动修复,或需要批量修复文件,可在终端执行命令:
# 修复单个文件
npx eslint --fix src/components/Button.tsx
# 修复整个项目
npx eslint --fix "src/**/*.{js,jsx,ts,tsx}" # 按你的文件模式调整
# 添加到 package.json 脚本(便捷执行)
# {
# "scripts": {
# "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
# "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix" // ✅ 一键修复
# }
# }
npm run lint:fix
4. 注意事项
- 并非所有的规则都支持自动修复,ESLint 规则分为「可自动修复」和 「需手动修复」两类:
- 可自动修复 : 如缩进、引号、分号、未使用变量等(规则名通常带 fixable 标记)
- 需手动修复 : 如逻辑错误( no-unsafe-assignment )、类型问题( @typescript-eslint/no-explicit-any )等
- 可以通过
eslint --fix-dry-run预览修复效果npx eslint --fix-dry-run src/App.tsx # 模拟修复,不实际修改文件 - 与
Prettier的配合(避免冲突)- 若同时使用 Prettier 格式化, 必须安装
eslint-config-prettier,它会关闭 ESLint 中与 Prettier 冲突的规则(如缩进、引号) - VSCode 中建议配置: Prettier 负责格式化,ESLint 负责代码质量 ,通过
editor.defaultFormatter指定 Prettier 为默认格式化工具,ESLint 仅做修复
- 若同时使用 Prettier 格式化, 必须安装
- 自动修复不生效的常见原因:
- VSCode 未启用自动修复 :检查
editor.codeActionsOnSave.source.fixAll.eslint是否为true - ESLint 扩展未激活 :打开 VSCode 输出面板(Ctrl+Shift+U),选择「ESLint」,查看是否有报错(如依赖缺失、配置错误)
- 文件未被 ESLint 处理 :检查 eslint.validate是否包含你的文件类型(如 .tsx)
- 规则不支持修复 :部分规则(如 @typescript-eslint/explicit-function-return-type)需手动添加返回类型
- VSCode 未启用自动修复 :检查
十二、简单示意
1. 安装
- react 全依赖版
- react 无可选依赖
- 库模式
npm install -D @eslint/js eslint-plugin-jsdoc eslint-config-prettier \
typescript-eslint eslint-plugin-unicorn eslint-plugin-promise \
eslint-plugin-no-use-extend-native eslint-plugin-import eslint-import-resolver-typescript \
eslint-plugin-alias eslint-plugin-unused-imports eslint-plugin-jsonc eslint-plugin-markdown \
eslint-plugin-perfectionist eslint prettier \
eslint-plugin-react eslint-plugin-react-hooks
npm install -D @eslint/js eslint-plugin-jsdoc eslint-config-prettier \
typescript-eslint eslint-plugin-promise eslint-import-resolver-typescript \
eslint-plugin-import eslint-plugin-unused-imports eslint-plugin-jsonc eslint \
prettier eslint-plugin-react eslint-plugin-react-hooks
npm install -D @eslint/js eslint-plugin-jsdoc eslint-config-prettier \
typescript-eslint eslint-plugin-promise eslint-plugin-import \
eslint-import-resolver-typescript eslint-plugin-unused-imports \
eslint-plugin-jsonc eslint prettier
2. 配置信息
- react 全依赖版
- react 无可选依赖
- 库模式
eslint.config.mjs
// eslint.config.mjs(ESM 格式)
import globals from 'globals'; // 全局变量(非插件,必备)
import js from '@eslint/js'; // 必须:核心推荐规则
import tseslint from 'typescript-eslint'; // 必须:TypeScript 支持
import reactPlugin from 'eslint-plugin-react'; // 必须:React 规则
import reactHooksPlugin from 'eslint-plugin-react-hooks'; // 必须:React Hooks 规则
import importPlugin from 'eslint-plugin-import'; // 必须:导入导出规范
import prettierConfig from 'eslint-config-prettier'; // 必须:关闭 Prettier 冲突规则
// 可选插件(按需启用)
import jsdocPlugin from 'eslint-plugin-jsdoc'; // 可选:JSDoc 注释
import unicornPlugin from 'eslint-plugin-unicorn'; // 可选:现代 JS/TS 最佳实践
import noExtendNativePlugin from 'eslint-plugin-no-use-extend-native'; // 可选:禁止扩展原生对象
import unusedImportsPlugin from 'eslint-plugin-unused-imports'; // 可选:删除未使用导入
import jsoncPlugin from 'eslint-plugin-jsonc'; // 可选:校验 JSON/JSONC
import markdownPlugin from 'eslint-plugin-markdown'; // 可选:校验 Markdown 代码块
import perfectionistPlugin from 'eslint-plugin-perfectionist'; // 可选:排序导入/属性
import promisePlugin from 'eslint-plugin-promise'; // 可选:Promise 规范
import mdxPlugin from 'eslint-plugin-mdx'; // 可选:Mdx 规范
import mdxParser from '@mdx-js/eslint-parser'; // 可选: Mdx 解析
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const tsconfigPath = resolve(__dirname, 'tsconfig.json');
const ignorePattern = [
'**/node_modules/',
'dist/',
'build/',
'coverage/',
'lib/',
'es/',
'**/test/**', // 匹配任何目录下的 test 目录
'**/*.test.ts', // 匹配任何目标下的 .test.ts 文件
'**/*.spec.ts', // 匹配 .spec.ts 文件
'**/*.min.js',
'pnpm-lock.yaml',
'package-lock.json',
'yarn.lock',
'.docusaurus',
'.wrangler',
];
export default [
// 0. 忽略文件配置
{
ignores: ignorePattern, // 优先配置忽略规则,提升配置
},
// 1. 基础配置(所有文件通用)
js.configs.recommended, // 必须:ESLint 核心推荐规则
{
languageOptions: {
globals: {
...globals.browser, // 浏览器全局变量
...globals.node, // Node.js 全局变量
},
},
},
// 2. TypeScript 配置(必须)
...tseslint.configs.recommended.map(config => ({
...config,
files: ['src/**/*.{ts,tsx}'], // 按需配置
languageOptions: {
...config.languageOptions,
globals: {
...globals.browser,
...globals.node,
...globals.es2025, // 浏览器 + Node + ES2025 全局
},
// parser: tseslint.parser, // 显式指定 TS 解析器,解决接口不匹配
parserOptions: {
...config.languageOptions?.parserOptions,
tsconfigRootDir: __dirname, // ESM 获取当前配置目录
project: [tsconfigPath], // 类型感知规则,或者指定实际的 tsconfig.json
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: { jsx: true }, // 开启JSX解析,适配React
},
},
plugin: {
...config?.plugin,
// 需要搭配安装 eslint-import-resolver-typescript
import: importPlugin,
'unused-imports': unusedImportsPlugin, // 内置未使用导入插件
},
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: {
project: tsconfigPath,
alwaysTryTypes: true,
},
node: true, // 兜底 node 解析器,兼容 commonjs/esm 混合模块
},
},
rules: {
// 原生规则对 TS 语法支持极差,必须关闭
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'warn',
{
vars: 'all',
args: 'after-used',
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'import/order': [
'error',
{
groups: [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index',
],
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
'import/no-duplicates': 'error',
'import/no-cycle': 'warn',
// 未使用的导入规则, error 强制级别删除,联动 ts-eslint 规则
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': 'off', // 与 '@typescript-eslint/no-unused-vars' 冲突
'@typescript-eslint/prefer-nullish-coalescing': 'error',
},
})),
// 3. React 配置(必须,React 项目)
{
files: ['**/*.{jsx,tsx}'], // 处理 JSX/TSX 文件
languageOptions: {
parserOptions: { ecmaFeatures: { jsx: true } }, // 启用 JSX
},
settings: { react: { version: 'detect' } }, // 自动检测 React 版本
plugins: {
react: reactPlugin, // 必须:注册 React 插件
'react-hooks': reactHooksPlugin, // 必须:注册 Hooks 插件
},
rules: {
// React 核心规则(必须)
'react/react-in-jsx-scope': 'off', // React 17+ 无需手动引入 React
'react/prop-types': 'off', // 用 TS 类型代替 PropTypes
// Hooks 规则(必须)
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
},
// 4. 可选插件配置(按需启用)
// 4.1 可选:JSDoc 注释规范
jsdocPlugin.configs['flat/recommended'],
{
files: ['**/*.{js,ts,jsx,tsx}'],
plugins: { jsdoc: jsdocPlugin },
rules: {
// 基础规则
'jsdoc/check-alignment': 'error',
'jsdoc/require-param': 'error',
'jsdoc/check-param-names': 'error',
'jsdoc/check-tag-names': [
'error',
{
// 配置允许的标签
definedTags: ['packageDocumentation', 'lastModified'],
},
],
'jsdoc/check-types': 'error',
// TypeScript 适配规则
'jsdoc/no-types': 'error',
'jsdoc/require-param-type': 'off', // 使用 TS 类型
'jsdoc/require-returns-type': 'off', // 使用 TS 类型
// 文档质量规则
'jsdoc/require-description': [
'error',
{
contexts: ['TSInterfaceDeclaration', 'TSTypeAliasDeclaration'],
},
],
'jsdoc/require-jsdoc': [
'warn',
{
require: {
FunctionDeclaration: true,
MethodDefinition: true,
ClassDeclaration: true,
},
},
],
},
// settings: {
// jsdoc: {
// // 用于配置首选项别名设置一个 JSDoc 标签
// tagNamePreference: {
// // eg.
// // "param": "arg",
// // "returns": "return",
// // todo: false, // 禁用 todo
// // todo: "禁用原因", // 禁用 todo ,并展示友好原因
// },
// },
// },
},
// 5.2 可选:现代 JS/TS 最佳实践(unicorn)
{
files: ['**/*.{js,ts,jsx,tsx}'],
plugins: { unicorn: unicornPlugin },
rules: {
'unicorn/prefer-array-find': 'error', // 用 find 替代 filter+[0]
'unicorn/no-null': 'warn', // 避免显式 null
},
},
// 5.3 可选:禁止扩展原生对象
{
plugins: { 'no-use-extend-native': noExtendNativePlugin },
rules: { 'no-use-extend-native/no-use-extend-native': 'error' },
},
// 5.4 可选:校验 JSON/JSONC 文件
{
files: ['**/*.json', '**/*.jsonc'],
plugins: { jsonc: jsoncPlugin },
rules: { 'jsonc/comma-dangle': ['error', 'never'] }, // JSON 禁止尾随逗号
},
// 5.5 可选:校验 Markdown 代码块
{
files: ['**/*.md'],
plugins: { markdown: markdownPlugin },
Processor: 'markdown/markdown', // 使用 markdown 处理提取代码块
rules: {
'markdown/remark': 'error',
'no-console': 'off',
}, // 用 remark 校验代码块
},
// 5.6 可选:校验 mdx 代码块
{
files: ['**/*.mdx'], // 处理 .mdx 文件
languageOptions: {
parser: mdxParser, // 使用 MDX 解析器
parserOptions: {
ecmaFeatures: { jsx: true }, // 启用 JSX
extraFileExtensions: ['.mdx'], // 声明 MDX 扩展名
},
},
plugins: { mdx: mdxPlugin },
rules: {
'mdx/no-jsx-html-comments': 'error', // MDX 专用规则(禁止 HTML 注释)
},
},
// 5.7 可选:排序导入/属性(perfectionist)
{
plugins: { perfectionist: perfectionistPlugin },
rules: {
'perfectionist/sort-imports': ['error', { type: 'natural' }], // 自然排序导入
'perfectionist/sort-objects': 'warn', // 排序对象属性
},
},
// 5.8 可选:Promise 规范(promise)
{
plugins: { promise: promisePlugin },
rules: {
'promise/always-return': 'error', // Promise 必须返回
'promise/no-return-wrap': 'error', // 禁止用 Promise.resolve 包裹
},
},
// 6. 关闭 Prettier 冲突规则(必须,用 Prettier 时)
prettierConfig,
];
eslint.config.mjs
// eslint.config.mjs(ESM 格式)
import globals from 'globals'; // 全局变量(非插件,必备)
import js from '@eslint/js'; // 必须:核心推荐规则
import tseslint from 'typescript-eslint'; // 必须:TypeScript 支持
import reactPlugin from 'eslint-plugin-react'; // 必须:React 规则
import reactHooksPlugin from 'eslint-plugin-react-hooks'; // 必须:React Hooks 规则
import importPlugin from 'eslint-plugin-import'; // 必须:导入导出规范
import prettierConfig from 'eslint-config-prettier'; // 必须:关闭 Prettier 冲突规则
// 可选插件(按需启用)
import jsdocPlugin from 'eslint-plugin-jsdoc'; // 可选:JSDoc 注释
import unusedImportsPlugin from 'eslint-plugin-unused-imports'; // 可选:删除未使用导入
import promisePlugin from 'eslint-plugin-promise'; // 可选:Promise 规范
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const tsconfigPath = resolve(__dirname, 'tsconfig.json');
const ignorePattern = [
'node_modules/',
'dist/',
'build/',
'coverage/',
'lib/',
'es/',
'**/test/**', // 匹配任何目录下的 test 目录
'**/*.test.ts', // 匹配任何目标下的 .test.ts 文件
'**/*.spec.ts', // 匹配 .spec.ts 文件
'**/*.min.js',
'pnpm-lock.yaml',
'package-lock.json',
'yarn.lock',
'.docusaurus',
'.wrangler',
];
export default [
// 0. 忽略文件配置
{
ignores: ignorePattern, // 优先配置忽略规则,提升性能
},
// 1. 基础配置(所有文件通用)
js.configs.recommended, // 必须:ESLint 核心推荐规则
{
languageOptions: {
globals: {
...globals.browser, // 浏览器全局变量
...globals.node, // Node.js 全局变量
},
},
},
// 2. TypeScript 配置(必须)
...tseslint.configs.recommended.map(config => ({
...config,
files: ['src/**/*.{ts,tsx}'], // 按需配置
languageOptions: {
...config.languageOptions,
globals: {
...globals.browser,
...globals.node,
...globals.es2025, // 浏览器 + Node + ES2025 全局
},
// parser: tseslint.parser, // 显式指定 TS 解析器,解决接口不匹配
parserOptions: {
...config.languageOptions?.parserOptions,
tsconfigRootDir: __dirname, // ESM 获取当前配置目录
project: [tsconfigPath], // 类型感知
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: { jsx: true }, // 开启JSX解析,适配React
},
},
plugins: {
...config?.plugins,
// 需要搭配安装 eslint-import-resolver-typescript
import: importPlugin,
'unused-imports': unusedImportsPlugin, // 内置未使用导入插件
},
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: {
project: tsconfigPath,
alwaysTryTypes: true,
},
node: true, // 兜底 node 解析器,兼容 commonjs/esm 混合模块
},
},
rules: {
// 原生规则对 TS 语法支持极差,必须关闭
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'warn',
{
vars: 'all',
args: 'after-used',
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'import/order': [
'error',
{
groups: [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index',
],
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
'import/no-duplicates': 'error',
'import/no-cycle': 'warn',
// 未使用的导入扶着, error 强制级别删除,联动 ts-eslint 规则
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': 'off', // 与 '@typescript-eslint/no-unused-vars' 冲突
},
})),
// 3. React 配置(必须,React 项目)
{
files: ['**/*.{jsx,tsx}'], // 处理 JSX/TSX 文件
languageOptions: {
parserOptions: { ecmaFeatures: { jsx: true } }, // 启用 JSX
},
settings: { react: { version: 'detect' } }, // 自动检测 React 版本
plugins: {
react: reactPlugin, // 必须:注册 React 插件
'react-hooks': reactHooksPlugin, // 必须:注册 Hooks 插件
},
rules: {
// React 核心规则(必须)
'react/react-in-jsx-scope': 'off', // React 17+ 无需手动引入 React
'react/prop-types': 'off', // 用 TS 类型代替 PropTypes
// Hooks 规则(必须)
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
},
// 4. 可选插件配置(按需启用)
// 4.1 可选:JSDoc 注释规范
{
files: ['**/*.{js,ts,jsx,tsx}'],
plugins: { jsdoc: jsdocPlugin },
rules: {
// 基础规则
'jsdoc/check-alignment': 'error',
'jsdoc/require-param': 'error',
'jsdoc/check-param-names': 'error',
'jsdoc/check-tag-names': [
'error',
{
// 配置允许的标签
definedTags: ['packageDocumentation', 'lastModified'],
},
],
'jsdoc/check-types': 'error',
// TypeScript 适配规则
'jsdoc/no-types': 'error',
'jsdoc/require-param-type': 'off', // 使用 TS 类型
'jsdoc/require-returns-type': 'off', // 使用 TS 类型
// 文档质量规则
'jsdoc/require-description': [
'error',
{
contexts: ['TSInterfaceDeclaration', 'TSTypeAliasDeclaration'],
},
],
'jsdoc/require-jsdoc': [
'warn',
{
require: {
FunctionDeclaration: true,
MethodDefinition: true,
ClassDeclaration: true,
},
},
],
},
// settings: {
// jsdoc: {
// // 用于配置首选项别名设置一个 JSDoc 标签
// tagNamePreference: {
// // eg.
// // "param": "arg",
// // "returns": "return",
// // todo: false, // 禁用 todo
// // todo: "禁用原因", // 禁用 todo ,并展示友好原因
// },
// },
// },
},
// 4.2 可选:Promise 规范(promise)
{
plugins: { promise: promisePlugin },
rules: {
'promise/always-return': 'error', // Promise 必须返回
'promise/no-return-wrap': 'error', // 禁止用 Promise.resolve 包裹
},
},
// 5. 关闭 Prettier 冲突规则(必须,用 Prettier 时)
prettierConfig,
];
eslint.config.mjs
// eslint.config.mjs(ESM 格式)
import globals from 'globals'; // 全局变量(非插件,必备)
import js from '@eslint/js'; // 必须:核心推荐规则
import tseslint from 'typescript-eslint'; // 必须:TypeScript 支持
import importPlugin from 'eslint-plugin-import'; // 必须:导入导出规范
import prettierConfig from 'eslint-config-prettier'; // 必须:关闭 Prettier 冲突规则
// 可选插件(按需启用)
import jsdocPlugin from 'eslint-plugin-jsdoc'; // 可选:JSDoc 注释
import unusedImportsPlugin from 'eslint-plugin-unused-imports'; // 可选:删除未使用导入
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const tsconfigPath = resolve(__dirname, 'tsconfig.json');
const ignorePattern = [
'node_modules/',
'dist/',
'build/',
'coverage/',
'lib/',
'es/',
'**/test/**', // 匹配任何目录下的 test 目录
'**/*.test.ts', // 匹配任何目标下的 .test.ts 文件
'**/*.spec.ts', // 匹配 .spec.ts 文件
'**/*.min.js',
'pnpm-lock.yaml',
'package-lock.json',
'yarn.lock',
'.docusaurus',
'.wrangler',
];
export default [
// 0. 忽略文件配置
{
ignores: ignorePattern, // 优先配置忽略规则,提升性能
},
// 1. 基础配置(所有文件通用)
js.configs.recommended, // 必须:ESLint 核心推荐规则
{
languageOptions: {
globals: {
...globals.browser, // 浏览器全局变量
...globals.node, // Node.js 全局变量
},
},
},
// 2. TypeScript 配置(必须)
...tseslint.configs.recommended.map(config => ({
...config,
files: ['src/**/*.{ts,tsx}'], // 按需配置
// ignores: ignorePattern,
languageOptions: {
...config.languageOptions,
globals: {
...globals.browser,
...globals.node,
...globals.es2025, // 浏览器 + Node + ES2025 全局
},
// parser: tseslint.parser, // 显式指定 TS 解析器,解决接口不匹配
parserOptions: {
...config.languageOptions?.parserOptions,
tsconfigRootDir: __dirname, // ESM 获取当前配置目录
project: [tsconfigPath], // 类型感知规则,或者指定实际的 tsconfig.json
ecmaVersion: 'latest',
sourceType: 'module',
// ecmaFeatures: { jsx: true }, // 开启JSX解析,适配React
},
},
plugins: {
...config?.plugins,
// 需要搭配安装 eslint-import-resolver-typescript
import: importPlugin,
'unused-imports': unusedImportsPlugin, // 内置未使用导入插件
},
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: {
project: tsconfigPath,
alwaysTryTypes: true,
},
node: true, // 兜底 node 解析器,兼容 commonjs/esm 混合模块
},
},
rules: {
// 原生规则对 TS 语法支持极差,必须关闭
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'warn',
{
vars: 'all',
args: 'after-used',
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'import/order': [
'error',
{
groups: [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index',
],
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
'import/no-duplicates': 'error',
'import/no-cycle': 'warn',
// 未使用的导入规则, error 强制级别删除,联动 ts-eslint 规则
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': 'off', // 与 '@typescript-eslint/no-unused-vars' 冲突
},
})),
// 3 可选:JSDoc 注释规范
{
files: ['**/*.{js,ts,jsx,tsx}'],
plugins: { jsdoc: jsdocPlugin },
rules: {
// 基础规则
'jsdoc/check-alignment': 'error',
'jsdoc/require-param': 'error',
'jsdoc/check-param-names': 'error',
'jsdoc/check-tag-names': [
'error',
{
// 配置允许的标签
definedTags: ['packageDocumentation','lastModified'],
},
],
'jsdoc/check-types': 'error',
// TypeScript 适配规则
'jsdoc/no-types': 'error',
'jsdoc/require-param-type': 'off', // 使用 TS 类型
'jsdoc/require-returns-type': 'off', // 使用 TS 类型
// 文档质量规则
'jsdoc/require-description': [
'error',
{
contexts: ['TSInterfaceDeclaration', 'TSTypeAliasDeclaration'],
},
],
'jsdoc/require-jsdoc': [
'warn',
{
require: {
FunctionDeclaration: true,
MethodDefinition: true,
ClassDeclaration: true,
},
},
],
// settings: {
// jsdoc: {
// // 用于配置首选项别名设置一个 JSDoc 标签
// tagNamePreference: {
// // eg.
// // "param": "arg",
// // "returns": "return",
// // todo: false, // 禁用 todo
// // todo: "禁用原因", // 禁用 todo ,并展示友好原因
// },
// },
// },
},
// 4. 关闭 Prettier 冲突规则(必须,用 Prettier 时)
prettierConfig,
];
3. 安装建议
| 插件 | 是否必须? | 说明 |
|---|---|---|
@eslint/js | ✅ 必须 | ESLint 官方 JS 推荐规则基础 |
typescript-eslint | ✅ TS 项目必须 | 没它 TS 文件无法正确 lint |
eslint-config-prettier | ✅ 强烈推荐 | 避免与 Prettier 格式冲突 |
eslint-plugin-import | ✅ 推荐 | 模块导入规范,大型项目必备 |
eslint-plugin-unused-imports | ✅ 推荐(尤其 TS) | 自动删未用 import ,提升整洁度 |
eslint-plugin-react + react-hooks | ⚠️ 仅 React 项目需要 | 非 React 项目可移除 |
eslint-plugin-jsdoc | ⚠️ 按需 | 文档驱动开发才需要,否则可关 |
eslint-plugin-promise | ⚠️ 按需 | 如果项目大量用 Promise,建议保留 |
eslint-plugin-jsonc | ⚠️ 按需 | 项目含 .jsonc(如 tsconfig.json )才需 |
eslint-plugin-unicorn | ❌ 可选 | 提供现代 JS 最佳实践,但非必需 |
eslint-plugin-no-use-extend-native | ❌ 可选 | 小众,除非团队明确禁止扩展原生对象 |
eslint-plugin-alias | ❌ 很少用 | 除非你用路径别名且想 lint 别名使用 |
eslint-plugin-markdown | ❌ 可选 | 仅当你在 Markdown 中写代码示例且想 lint |
eslint-plugin-perfectionist | ❌ 可选 | 专注于 import/object 排序,与 import/order 功能重叠 |