> 技术文档 > ESLint从入门到实战_.eslintrc.js的globals

ESLint从入门到实战_.eslintrc.js的globals


ESLint从入门到实战_.eslintrc.js的globals


引言

作为前端开发者,你是否遇到过这样的情况:团队成员写出的代码风格各异,有人喜欢用分号,有人不用;有人用双引号,有人用单引号;代码评审时总是在纠结这些格式问题而不是业务逻辑?或者在大型项目中,因为一个未定义的变量导致生产环境报错?

ESLint 就是为了解决这些问题而生的。它不仅能统一代码风格,更重要的是能在开发阶段就发现潜在的错误,提高代码质量和开发效率。

本文将从零开始,带你全面掌握 ESLint 的使用,从基础配置到高级定制,从个人项目到团队协作,让你成为 ESLint 的专家。

什么是ESLint?

定义与作用

ESLint 是一个开源的 JavaScript 代码静态分析工具,由 Nicholas C. Zakas 在 2013 年创建。它的主要作用是:

  1. 代码质量检查:识别有问题的模式或不符合特定规则的代码
  2. 代码风格统一:强制执行一致的代码风格
  3. 错误预防:在运行前捕获潜在的错误
  4. 最佳实践提醒:推广 JavaScript 最佳实践

核心特性

  • 完全可配置:所有规则都可以开启/关闭,每个规则都有多个设置选项
  • 插件化架构:可以通过插件扩展功能,支持 TypeScript、React、Vue 等
  • 支持多种配置格式:JSON、YAML、JavaScript 等
  • IDE 集成:主流编辑器都有相应插件
  • 自动修复:大部分格式问题可以自动修复

安装与基础配置

安装ESLint

# 全局安装(不推荐)npm install -g eslint# 项目内安装(推荐)npm install --save-dev eslint# 使用 yarnyarn add --dev eslint# 使用 pnpmpnpm add -D eslint

初始化配置

# 交互式创建配置文件npx eslint --init# 或者使用npm init @eslint/config

执行命令后,ESLint 会问你几个问题:

  1. How would you like to use ESLint?

    • To check syntax only(仅检查语法)
    • To check syntax and find problems(检查语法并发现问题)
    • To check syntax, find problems, and enforce code style(检查语法、发现问题并强制代码风格)
  2. What type of modules does your project use?

    • JavaScript modules (import/export)
    • CommonJS (require/exports)
    • None of these
  3. Which framework does your project use?

    • React
    • Vue.js
    • None of these
  4. Does your project use TypeScript? Yes/No

  5. Where does your code run?

    • Browser
    • Node
  6. What format do you want your config file to be in?

    • JavaScript
    • YAML
    • JSON

基础配置文件示例

根据你的选择,ESLint 会生成对应的配置文件。以 .eslintrc.js 为例:

module.exports = { // 环境定义 env: { browser: true, es2021: true, node: true }, // 继承的配置 extends: [ \'eslint:recommended\' ], // 解析器选项 parserOptions: { ecmaVersion: 12, sourceType: \'module\' }, // 自定义规则 rules: { // 在这里添加或覆盖规则 }};

配置文件详解

配置文件类型与优先级

ESLint 支持多种配置文件格式,优先级从高到低:

  1. .eslintrc.js
  2. .eslintrc.cjs
  3. .eslintrc.yaml.eslintrc.yml
  4. .eslintrc.json
  5. package.json 中的 eslintConfig 字段

核心配置选项

1. env(环境配置)

定义代码运行的环境,影响全局变量的可用性:

module.exports = { env: { browser: true, // 浏览器全局变量 node: true, // Node.js 全局变量 es2021: true, // ES2021 语法支持 jest: true, // Jest 测试环境 jquery: true, // jQuery 全局变量 worker: true, // Web Worker serviceworker: true // Service Worker }};
2. extends(扩展配置)

继承其他的配置文件或预设规则集:

module.exports = { extends: [ \'eslint:recommended\',  // ESLint 推荐规则 \'@typescript-eslint/recommended\', // TypeScript 推荐规则 \'plugin:react/recommended\', // React 推荐规则 \'plugin:vue/essential\', // Vue 基础规则 \'airbnb\',// Airbnb 风格指南 \'prettier\'  // Prettier 兼容 ]};
3. parser(解析器)

指定 ESLint 使用的解析器:

module.exports = { // TypeScript 解析器 parser: \'@typescript-eslint/parser\', // Babel 解析器 // parser: \'@babel/eslint-parser\', parserOptions: { ecmaVersion: 2021, sourceType: \'module\', ecmaFeatures: { jsx: true,  // 支持 JSX globalReturn: true, // 允许全局 return impliedStrict: true // 启用严格模式 } }};
4. plugins(插件)

扩展 ESLint 功能的插件:

module.exports = { plugins: [ \'@typescript-eslint\', // TypeScript 插件 \'react\',  // React 插件 \'react-hooks\', // React Hooks 插件 \'import\', // import/export 插件 \'jsx-a11y\',  // 无障碍访问插件 \'prettier\' // Prettier 插件 ]};
5. rules(规则配置)

这是 ESLint 的核心,定义具体的检查规则:

module.exports = { rules: { // 错误级别: \"off\" 或 0, \"warn\" 或 1, \"error\" 或 2 // 代码质量相关 \'no-unused-vars\': \'error\', // 禁止未使用的变量 \'no-undef\': \'error\',  // 禁止使用未定义的变量 \'no-console\': \'warn\', // 警告使用 console \'no-debugger\': \'error\',  // 禁止使用 debugger // 代码风格相关 \'indent\': [\'error\', 2],  // 强制缩进为 2 个空格 \'quotes\': [\'error\', \'single\'], // 强制使用单引号 \'semi\': [\'error\', \'always\'], // 强制使用分号 \'comma-dangle\': [\'error\', \'never\'], // 禁止末尾逗号 // ES6+ 相关 \'prefer-const\': \'error\', // 优先使用 const \'arrow-spacing\': \'error\', // 箭头函数空格 \'template-curly-spacing\': \'error\', // 模板字符串空格 // 函数相关 \'func-style\': [\'error\', \'declaration\'], // 函数声明风格 \'max-params\': [\'error\', 4], // 最多 4 个参数 // 对象和数组 \'object-curly-spacing\': [\'error\', \'always\'], // 对象花括号空格 \'array-bracket-spacing\': [\'error\', \'never\'], // 数组方括号空格 }};

高级配置选项

1. globals(全局变量)

定义额外的全局变量:

module.exports = { globals: { myCustomGlobal: \'readonly\', // 只读 anotherGlobal: \'writable\', // 可写 $: \'readonly\',  // jQuery _: \'readonly\' // Lodash }};
2. overrides(覆盖配置)

为特定文件或目录设置不同的规则:

module.exports = { rules: { // 全局规则 \'no-console\': \'error\' }, overrides: [ { // 对测试文件的特殊配置 files: [\'**/*.test.js\', \'**/*.spec.js\'], env: { jest: true }, rules: { \'no-console\': \'off\' // 测试文件允许使用 console } }, { // 对 TypeScript 文件的配置 files: [\'**/*.ts\', \'**/*.tsx\'], parser: \'@typescript-eslint/parser\', plugins: [\'@typescript-eslint\'], rules: { \'@typescript-eslint/no-unused-vars\': \'error\' } } ]};
3. ignorePatterns(忽略模式)

指定要忽略的文件和目录:

module.exports = { ignorePatterns: [ \'dist/\', \'build/\', \'node_modules/\', \'*.min.js\', \'coverage/\' ]};

常用规则详解

代码质量规则

1. 变量相关
{ // 禁止使用未声明的变量 \'no-undef\': \'error\', // 禁止未使用的变量 \'no-unused-vars\': [\'error\', { vars: \'all\',  // 检查所有变量 args: \'after-used\', // 检查使用后的参数 ignoreRestSiblings: true // 忽略剩余兄弟元素 }], // 禁止重复声明变量 \'no-redeclare\': \'error\', // 禁止在变量定义之前使用 \'no-use-before-define\': [\'error\', { functions: false, // 函数声明提升 classes: true, variables: true }]}
2. 函数相关
{ // 要求或禁止使用命名的 function 表达式 \'func-names\': [\'error\', \'as-needed\'], // 强制函数最大行数 \'max-lines-per-function\': [\'error\', { max: 50, skipBlankLines: true, skipComments: true }], // 限制函数参数数量 \'max-params\': [\'error\', 4], // 禁止使用 arguments.caller 或 arguments.callee \'no-caller\': \'error\'}
3. 对象和数组
{ // 禁止对象字面量中出现重复的 key \'no-dupe-keys\': \'error\', // 禁止数组中出现重复的元素 \'no-dupe-args\': \'error\', // 强制对象字面量属性名称使用一致的引号 \'quote-props\': [\'error\', \'as-needed\'], // 要求对象字面量简写语法 \'object-shorthand\': [\'error\', \'always\']}

代码风格规则

1. 空格和缩进
{ // 强制使用一致的缩进 \'indent\': [\'error\', 2, { SwitchCase: 1, // switch 语句缩进 VariableDeclarator: 1, // 变量声明缩进 outerIIFEBody: 1 // IIFE 缩进 }], // 强制在逗号前后使用一致的空格 \'comma-spacing\': [\'error\', { before: false, after: true }], // 强制在对象字面量的属性中键和值之间使用一致的间距 \'key-spacing\': [\'error\', { beforeColon: false, afterColon: true }]}
2. 引号和分号
{ // 强制使用一致的引号 \'quotes\': [\'error\', \'single\', { avoidEscape: true, // 避免转义 allowTemplateLiterals: true // 允许模板字符串 }], // 要求或禁止使用分号 \'semi\': [\'error\', \'always\'], // 强制分号之前和之后使用一致的空格 \'semi-spacing\': [\'error\', { before: false, after: true }]}

ES6+ 规则

{ // 要求使用 const 声明那些声明后不再被修改的变量 \'prefer-const\': \'error\', // 要求使用箭头函数作为回调 \'prefer-arrow-callback\': \'error\', // 要求使用模板字面量而非字符串连接 \'prefer-template\': \'error\', // 强制箭头函数的箭头前后使用一致的空格 \'arrow-spacing\': [\'error\', { before: true, after: true }], // 要求解构赋值 \'prefer-destructuring\': [\'error\', { array: true, object: true }]}

实际项目配置示例

React项目配置

module.exports = { env: { browser: true, es2021: true, node: true }, extends: [ \'eslint:recommended\', \'plugin:react/recommended\', \'plugin:react-hooks/recommended\', \'plugin:jsx-a11y/recommended\' ], parser: \'@babel/eslint-parser\', parserOptions: { ecmaFeatures: { jsx: true }, ecmaVersion: 12, sourceType: \'module\', requireConfigFile: false, babelOptions: { presets: [\'@babel/preset-react\'] } }, plugins: [ \'react\', \'react-hooks\', \'jsx-a11y\' ], rules: { // React 相关 \'react/prop-types\': \'error\', \'react/jsx-uses-react\': \'off\', \'react/react-in-jsx-scope\': \'off\', \'react/jsx-filename-extension\': [1, { extensions: [\'.js\', \'.jsx\'] }], // React Hooks \'react-hooks/rules-of-hooks\': \'error\', \'react-hooks/exhaustive-deps\': \'warn\', // JSX 相关 \'jsx-quotes\': [\'error\', \'prefer-double\'], \'react/jsx-indent\': [\'error\', 2], \'react/jsx-indent-props\': [\'error\', 2] }, settings: { react: { version: \'detect\' } }};

TypeScript项目配置

module.exports = { env: { browser: true, es2021: true, node: true }, extends: [ \'eslint:recommended\', \'@typescript-eslint/recommended\', \'@typescript-eslint/recommended-requiring-type-checking\' ], parser: \'@typescript-eslint/parser\', parserOptions: { ecmaVersion: 12, sourceType: \'module\', project: \'./tsconfig.json\' }, plugins: [ \'@typescript-eslint\' ], rules: { // TypeScript 特定规则 \'@typescript-eslint/no-unused-vars\': \'error\', \'@typescript-eslint/no-explicit-any\': \'warn\', \'@typescript-eslint/explicit-function-return-type\': \'off\', \'@typescript-eslint/explicit-module-boundary-types\': \'off\', \'@typescript-eslint/no-non-null-assertion\': \'warn\', // 类型检查 \'@typescript-eslint/strict-boolean-expressions\': \'error\', \'@typescript-eslint/prefer-nullish-coalescing\': \'error\', \'@typescript-eslint/prefer-optional-chain\': \'error\', // 命名约定 \'@typescript-eslint/naming-convention\': [ \'error\', { selector: \'interface\', format: [\'PascalCase\'], prefix: [\'I\'] }, { selector: \'typeAlias\', format: [\'PascalCase\'] }, { selector: \'enum\', format: [\'PascalCase\'] } ] }};

Node.js项目配置

module.exports = { env: { node: true, es2021: true }, extends: [ \'eslint:recommended\' ], parserOptions: { ecmaVersion: 12, sourceType: \'module\' }, rules: { // Node.js 特定规则 \'no-process-exit\': \'error\', \'no-process-env\': \'off\', \'global-require\': \'error\', // 回调函数 \'callback-return\': \'error\', \'handle-callback-err\': \'error\', // Buffer 相关 \'no-buffer-constructor\': \'error\', // 路径相关 \'no-path-concat\': \'error\', // 同步方法 \'no-sync\': \'warn\' }};

命令行使用

基本命令

# 检查单个文件npx eslint file.js# 检查多个文件npx eslint file1.js file2.js# 检查目录npx eslint src/# 检查特定扩展名的文件npx eslint src/ --ext .js,.jsx,.ts,.tsx# 自动修复可修复的问题npx eslint src/ --fix# 输出格式化npx eslint src/ --format tablenpx eslint src/ --format json

高级命令选项

# 忽略 .eslintignore 文件npx eslint src/ --no-ignore# 指定配置文件npx eslint src/ --config .eslintrc.custom.js# 只运行特定规则npx eslint src/ --rule \'quotes: error\'# 禁用特定规则npx eslint src/ --rule \'no-console: off\'# 缓存结果以提高性能npx eslint src/ --cache# 指定缓存位置npx eslint src/ --cache --cache-location .eslintcache# 最大警告数npx eslint src/ --max-warnings 0

package.json 脚本配置

{ \"scripts\": { \"lint\": \"eslint src/\", \"lint:fix\": \"eslint src/ --fix\", \"lint:check\": \"eslint src/ --max-warnings 0\", \"lint:cache\": \"eslint src/ --cache\", \"precommit\": \"lint-staged\" }, \"lint-staged\": { \"*.{js,jsx,ts,tsx}\": [ \"eslint --fix\", \"git add\" ] }}

IDE集成

VS Code集成

  1. 安装ESLint插件

    • 在扩展商店搜索 “ESLint”
    • 安装官方的 ESLint 插件
  2. 配置settings.json

{ \"eslint.enable\": true, \"eslint.autoFixOnSave\": true, \"eslint.validate\": [ \"javascript\", \"javascriptreact\", \"typescript\", \"typescriptreact\" ], \"editor.codeActionsOnSave\": { \"source.fixAll.eslint\": true }, \"eslint.workingDirectories\": [\"./src\"]}

WebStorm/IDEA集成

  1. 打开 Settings/Preferences
  2. 导航到 Languages & Frameworks > JavaScript > Code Quality Tools > ESLint
  3. 勾选 “Automatic ESLint configuration”
  4. 配置 “Run eslint --fix on save”

与其他工具集成

与Prettier集成

# 安装相关包npm install --save-dev prettier eslint-config-prettier eslint-plugin-prettier# .eslintrc.js 配置module.exports = { extends: [ \'eslint:recommended\', \'prettier\' // 必须放在最后 ], plugins: [\'prettier\'], rules: { \'prettier/prettier\': \'error\' }};# .prettierrc 配置{ \"semi\": true, \"trailingComma\": \"es5\", \"singleQuote\": true, \"printWidth\": 80, \"tabWidth\": 2}

与Husky和lint-staged集成

# 安装npm install --save-dev husky lint-staged# package.json 配置{ \"husky\": { \"hooks\": { \"pre-commit\": \"lint-staged\" } }, \"lint-staged\": { \"*.{js,jsx,ts,tsx}\": [ \"eslint --fix\", \"prettier --write\", \"git add\" ] }}

与Webpack集成

// webpack.config.jsconst ESLintPlugin = require(\'eslint-webpack-plugin\');module.exports = { plugins: [ new ESLintPlugin({ extensions: [\'js\', \'jsx\', \'ts\', \'tsx\'], fix: true, cache: true }) ]};

自定义规则开发

创建简单的自定义规则

// rules/no-console-log.jsmodule.exports = { meta: { type: \'suggestion\', docs: { description: \'Disallow console.log statements\', category: \'Best Practices\', recommended: false }, fixable: \'code\', schema: [] }, create(context) { return { CallExpression(node) { if ( node.callee.type === \'MemberExpression\' && node.callee.object.name === \'console\' && node.callee.property.name === \'log\' ) { context.report({ node, message: \'console.log is not allowed\', fix(fixer) {  return fixer.remove(node.parent); } }); } } }; }};

使用自定义规则

// .eslintrc.jsmodule.exports = { rules: { \'local/no-console-log\': \'error\' }, plugins: [\'local\']};// eslint-plugin-local/index.jsmodule.exports = { rules: { \'no-console-log\': require(\'./rules/no-console-log\') }};

性能优化

缓存配置

# 启用缓存npx eslint src/ --cache# 指定缓存文件位置npx eslint src/ --cache --cache-location node_modules/.cache/eslint

并行处理

{ \"scripts\": { \"lint:parallel\": \"eslint src/ --cache --fix --max-warnings 0\" }}

忽略文件配置

# .eslintignorenode_modules/dist/build/coverage/*.min.js*.bundle.jspublic/

团队协作最佳实践

1. 统一配置管理

// eslint-config-company/index.jsmodule.exports = { extends: [ \'eslint:recommended\', \'@typescript-eslint/recommended\' ], rules: { // 公司统一规则 \'indent\': [\'error\', 2], \'quotes\': [\'error\', \'single\'], \'semi\': [\'error\', \'always\'] }};// 项目中使用// .eslintrc.jsmodule.exports = { extends: [\'@company/eslint-config\']};

2. 渐进式引入

// 第一阶段:只启用错误级别规则module.exports = { extends: [\'eslint:recommended\'], rules: { // 只修复明显错误 \'no-unused-vars\': \'error\', \'no-undef\': \'error\' }};// 第二阶段:添加警告级别规则module.exports = { extends: [\'eslint:recommended\'], rules: { \'no-unused-vars\': \'error\', \'no-undef\': \'error\', \'no-console\': \'warn\', // 新增警告 \'prefer-const\': \'warn\' }};// 第三阶段:提升为错误级别module.exports = { extends: [\'eslint:recommended\'], rules: { \'no-unused-vars\': \'error\', \'no-undef\': \'error\', \'no-console\': \'error\', // 提升为错误 \'prefer-const\': \'error\' }};

3. CI/CD 集成

# .github/workflows/lint.ymlname: Linton: [push, pull_request]jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: node-version: \'16\' - run: npm ci - run: npm run lint:check

常见问题与解决方案

1. 解析错误

问题:Parsing error: Unexpected token
解决:检查解析器配置,确保支持使用的语法特性

module.exports = { parser: \'@babel/eslint-parser\', parserOptions: { ecmaVersion: 2021, sourceType: \'module\', requireConfigFile: false }};

2. 规则冲突

问题:ESLint 和 Prettier 规则冲突
解决:使用 eslint-config-prettier

module.exports = { extends: [ \'eslint:recommended\', \'prettier\' // 必须放在最后,覆盖冲突规则 ]};

3. 性能问题

问题:ESLint 运行很慢
解决

  • 启用缓存:--cache
  • 使用 .eslintignore 忽略不必要的文件
  • 考虑使用 eslint_d
# 安装 eslint_d(ESLint 守护进程)npm install -g eslint_d# 使用 eslint_d 替代 eslinteslint_d src/

4. 内存溢出

问题:JavaScript heap out of memory
解决:增加 Node.js 内存限制

{ \"scripts\": { \"lint\": \"node --max-old-space-size=4096 node_modules/.bin/eslint src/\" }}