ESLint 和 Prettier 代码质量工具配置

ESLint 和 Prettier 是现代 JavaScript 开发中不可或缺的代码质量工具,它们帮助我们维护一致的代码风格、发现潜在错误,并确保代码遵循最佳实践。

  • 作用: 静态代码分析工具,检查代码错误和风格问题
  • 功能: 语法错误检测、代码规范检查、最佳实践建议
  • 配置: 高度可配置,支持自定义规则
  • 作用: 代码格式化工具,自动格式化代码
  • 功能: 统一代码风格、自动格式化、保存时格式化
  • 特点: 固执己见的格式化,减少配置复杂度
  • ESLint: 关注代码质量和逻辑错误
  • Prettier: 关注代码格式和视觉呈现
  • 配合使用: ESLint 负责逻辑检查,Prettier 负责格式化
# 安装 ESLint
npm install --save-dev eslint

# 交互式初始化配置
npx eslint --init

交互式配置选项:

  • How would you like to use ESLint? → 检查语法和问题
  • What type of modules? → ES6 模块
  • Which framework? → None / React / Vue
  • Does your project use TypeScript? → No
  • Where does your code run? → Browser / Node
  • What format? → JavaScript

创建 .eslintrc.js 文件:

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
    jest: true,
  },
  extends: [
    'eslint:recommended',
  ],
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
  },
  rules: {
    // 错误级别规则
    'no-console': 'warn',
    'no-unused-vars': 'error',
    'no-undef': 'error',
    
    // 代码风格规则
    'prefer-const': 'error',
    'no-var': 'error',
    'arrow-spacing': 'error',
    'comma-dangle': ['error', 'always-multiline'],
    
    // 最佳实践
    'eqeqeq': ['error', 'always'],
    'curly': ['error', 'all'],
    'no-eval': 'error',
  },
};
# 安装 Prettier
npm install --save-dev prettier

# 安装 ESLint 和 Prettier 集成插件
npm install --save-dev eslint-config-prettier eslint-plugin-prettier

创建 .prettierrc 文件:

{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "bracketSpacing": true,
  "arrowParens": "always",
  "endOfLine": "lf"
}

更新 .eslintrc.js 以集成 Prettier:

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
    jest: true,
  },
  extends: [
    'eslint:recommended',
    'prettier', // 必须放在最后,禁用与 Prettier 冲突的规则
  ],
  plugins: ['prettier'],
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
  },
  rules: {
    // Prettier 集成
    'prettier/prettier': 'error',
    
    // ESLint 规则
    'no-console': 'warn',
    'no-unused-vars': 'error',
    'prefer-const': 'error',
    'no-var': 'error',
  },
};
{
  env: {
    browser: true,     // 浏览器全局变量
    node: true,        // Node.js 全局变量
    es2021: true,      // ES2021 语法支持
    jest: true,        // Jest 测试框架
    jquery: true,      // jQuery 全局变量
    worker: true,      // Web Workers
  }
}
{
  extends: [
    'eslint:recommended',           // ESLint 推荐规则
    '@eslint/js/recommended',      // 新版推荐配置
    'airbnb-base',                 // Airbnb 规范
    'standard',                    // Standard 规范
    'prettier',                    // Prettier 集成
  ]
}
{
  parserOptions: {
    ecmaVersion: 'latest',    // 支持的 ECMAScript 版本
    sourceType: 'module',     // 模块类型: 'module' | 'script'
    ecmaFeatures: {
      jsx: true,              // 启用 JSX
      globalReturn: true,     // 允许全局 return
    }
  }
}
{
  rules: {
    // 规则级别: 'off' | 'warn' | 'error' 或 0 | 1 | 2
    
    // 可能的错误
    'no-console': 'warn',
    'no-debugger': 'error',
    'no-unused-vars': 'error',
    'no-undef': 'error',
    
    // 最佳实践
    'eqeqeq': ['error', 'always'],
    'curly': ['error', 'all'],
    'no-eval': 'error',
    'no-implicit-globals': 'error',
    
    // 变量相关
    'prefer-const': 'error',
    'no-var': 'error',
    'no-use-before-define': 'error',
    
    // ES6+ 特性
    'arrow-spacing': 'error',
    'prefer-arrow-callback': 'error',
    'prefer-template': 'error',
    'object-shorthand': 'error',
  }
}
{
  "printWidth": 80,           // 每行最大字符数
  "tabWidth": 2,              // 缩进宽度
  "useTabs": false,           // 使用制表符缩进
  "semi": true,               // 行尾分号
  "singleQuote": true,        // 使用单引号
  "quoteProps": "as-needed",  // 对象属性引号: "as-needed" | "consistent" | "preserve"
  "trailingComma": "es5",     // 尾逗号: "es5" | "none" | "all"
  "bracketSpacing": true,     // 对象括号空格
  "arrowParens": "always",    // 箭头函数参数括号: "always" | "avoid"
  "endOfLine": "lf"           // 换行符: "lf" | "crlf" | "cr" | "auto"
}
{
  "bracketSameLine": false,   // JSX 括号位置
  "embeddedLanguageFormatting": "auto", // 嵌入语言格式化
  "htmlWhitespaceSensitivity": "css",   // HTML 空白敏感性
  "insertPragma": false,      // 插入 @format 注释
  "requirePragma": false,     // 需要 @format 注释
  "proseWrap": "preserve"     // Markdown 文本换行
}

package.json 中添加脚本:

{
  "scripts": {
    "lint": "eslint src tests",
    "lint:fix": "eslint src tests --fix",
    "lint:watch": "nodemon --exec \"npm run lint\" --watch src --ext js",
    "format": "prettier --write \"src/**/*.js\" \"tests/**/*.js\"",
    "format:check": "prettier --check \"src/**/*.js\" \"tests/**/*.js\"",
    "check": "npm run lint && npm run format:check"
  }
}
  • lint: 检查代码问题
  • lint:fix: 自动修复可修复的问题
  • format: 格式化代码
  • format:check: 检查格式化状态
  • check: 同时运行 lint 和格式检查
# 构建输出
dist/
build/
coverage/

# 依赖
node_modules/

# 配置文件
*.config.js
webpack.config.js

# 测试相关
__mocks__/
# 构建输出
dist/
build/
coverage/

# 依赖
node_modules/

# 配置文件
package.json
package-lock.json

# 其他
*.min.js
*.md

创建项目特定的规则配置:

// .eslintrc.js
module.exports = {
  extends: ['eslint:recommended', 'prettier'],
  plugins: ['prettier'],
  rules: {
    // 自定义严格规则
    'prettier/prettier': 'error',
    
    // 变量和函数
    'no-unused-vars': ['error', { 
      vars: 'all', 
      args: 'after-used',
      ignoreRestSiblings: true 
    }],
    'prefer-const': 'error',
    'no-var': 'error',
    
    // 函数相关
    'arrow-spacing': 'error',
    'prefer-arrow-callback': 'error',
    'func-style': ['error', 'expression'],
    
    // 对象和数组
    'object-shorthand': 'error',
    'prefer-destructuring': ['error', {
      array: true,
      object: true
    }],
    
    // 字符串
    'prefer-template': 'error',
    'template-curly-spacing': ['error', 'never'],
    
    // 比较和条件
    'eqeqeq': ['error', 'always'],
    'no-implicit-coercion': 'error',
    'yoda': ['error', 'never'],
    
    // 错误处理
    'no-throw-literal': 'error',
    'prefer-promise-reject-errors': 'error',
  },
};
module.exports = {
  // 基础配置
  extends: ['eslint:recommended', 'prettier'],
  
  // 覆盖特定文件的配置
  overrides: [
    {
      // 测试文件配置
      files: ['**/*.test.js', '**/*.spec.js'],
      env: {
        jest: true,
      },
      rules: {
        'no-console': 'off', // 测试中允许 console
      },
    },
    {
      // Node.js 脚本配置
      files: ['scripts/**/*.js', '*.config.js'],
      env: {
        node: true,
        browser: false,
      },
      rules: {
        'no-console': 'off', // 脚本中允许 console
      },
    },
  ],
};

创建可共享的配置包:

// eslint-config-myteam/index.js
module.exports = {
  extends: [
    'eslint:recommended',
    'prettier',
  ],
  plugins: ['prettier'],
  rules: {
    // 团队统一规则
    'prettier/prettier': 'error',
    'no-console': 'warn',
    'prefer-const': 'error',
    // ... 更多规则
  },
  overrides: [
    // 针对不同项目类型的配置
  ],
};

使用共享配置:

// .eslintrc.js
module.exports = {
  extends: ['myteam'],
};

.vscode/settings.json 中配置:

{
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "eslint.alwaysShowStatus": true,
  "prettier.requireConfig": true,
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

推荐安装的 VS Code 插件:

  • ESLint
  • Prettier - Code formatter
  • Error Lens (显示错误行内提示)

创建 .editorconfig 文件:

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false

[*.{json,yml,yaml}]
indent_size = 2

问题: 格式化规则冲突
解决: 确保正确配置集成

# 安装冲突解决包
npm install --save-dev eslint-config-prettier eslint-plugin-prettier
// .eslintrc.js
module.exports = {
  extends: [
    'eslint:recommended',
    'prettier' // 必须放在最后
  ],
  plugins: ['prettier'],
  rules: {
    'prettier/prettier': 'error'
  }
};

问题: ESLint 检查速度慢
解决: 优化配置和使用缓存

# 使用缓存
npx eslint --cache src/
// .eslintrc.js
module.exports = {
  // 启用缓存
  cache: true,
  cacheLocation: '.eslintcache',
  
  // 忽略不需要检查的文件
  ignorePatterns: ['dist/', 'node_modules/'],
};

问题: 某些规则过于严格或宽松
解决: 自定义规则级别

{
  rules: {
    // 将错误降级为警告
    'no-console': 'warn',
    
    // 禁用特定规则
    'no-unused-vars': 'off',
    
    // 自定义规则选项
    'max-len': ['error', { 
      code: 100, 
      ignoreUrls: true 
    }]
  }
}

创建测试文件 src/test-lint.js

// 故意包含一些问题的代码
var unused = 'test'
const name = "John"  // 双引号问题
let age=25 // 空格问题

function hello( ) {  // 空格问题
console.log("Hello " + name ) // 字符串拼接问题
}

// 未使用的变量
let anotherVar = 'unused';

运行检查:

npm run lint
npm run format

验证 ESLint 和 Prettier 是否正确协作:

# 先格式化
npm run format

# 再检查
npm run lint

应该没有格式相关的 ESLint 错误。

代码质量工具配置完成后,继续配置其他开发工具:

  1. Jest 单元测试框架配置