Appearance
ESLint最佳实践
本指南介绍在项目中使用ESLint的最佳实践,帮助您建立高效的代码质量保证体系。
项目初始化
选择合适的配置策略
bash
# 使用ESLint初始化向导
npx eslint --init
选择配置时的考虑因素:
- 项目类型(React, Vue, Node.js等)
- 代码风格(是否使用TypeScript)
- 团队偏好(严格的规则还是灵活的规则)
基础配置示例
javascript
// .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'eslint:recommended',
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
rules: {
// 从较宽松的规则开始,逐步收紧
'no-console': 'warn',
'no-debugger': 'error',
},
};
规则管理
分类管理规则
javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
// 按功能扩展
'plugin:import/recommended',
'plugin:react/recommended',
],
rules: {
// 1. 代码质量规则
'no-console': 'warn',
'no-alert': 'error',
'no-unused-vars': 'error',
// 2. 代码风格规则
'semi': ['error', 'always'],
'quotes': ['error', 'single'],
// 3. 最佳实践规则
'eqeqeq': 'error',
'no-var': 'error',
},
};
渐进式规则收紧
javascript
// 开发阶段使用较宽松的规则
module.exports = {
rules: {
'no-console': 'warn', // 只警告
'no-unused-vars': 'warn',
},
};
// 生产阶段使用严格的规则
module.exports = {
rules: {
'no-console': 'error', // 报错并中断构建
'no-unused-vars': 'error',
},
};
项目配置
多环境配置
javascript
// .eslintrc.js
module.exports = {
extends: ['eslint:recommended'],
overrides: [
// 测试文件配置
{
files: ['**/*.test.js', '**/*.spec.js'],
env: {
jest: true,
node: true,
},
rules: {
'no-console': 'off',
'no-unused-vars': 'off',
},
},
// 服务端文件配置
{
files: ['src/server/**/*.js'],
env: {
node: true,
},
rules: {
'no-process-exit': 'error',
'no-sync': 'error',
},
},
],
};
工作区配置
javascript
// .eslintrc.js - 根配置
module.exports = {
root: true,
extends: ['eslint:recommended'],
overrides: [
{
files: ['packages/frontend/**/*.js'],
extends: [
'eslint:recommended',
'plugin:react/recommended',
],
settings: {
react: {
version: 'detect',
},
},
},
{
files: ['packages/backend/**/*.js'],
extends: ['eslint:recommended'],
env: {
node: true,
},
},
],
};
团队协作
共享配置
javascript
// packages/eslint-config-custom/index.js
module.exports = {
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
'no-alert': 'error',
},
env: {
browser: true,
node: true,
es6: true,
},
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
},
};
json
// packages/eslint-config-custom/package.json
{
"name": "@company/eslint-config",
"version": "1.0.0",
"main": "index.js",
"peerDependencies": {
"eslint": "^8.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0"
},
"keywords": [
"eslint",
"config",
"company",
"shared"
]
}
配置继承
javascript
// 项目中的.eslintrc.js
module.exports = {
extends: [
'@company/eslint-config', // 使用共享配置
'plugin:react/recommended', // 添加特定插件
],
rules: {
// 项目特定的规则覆盖
'no-console': 'error', // 比共享配置更严格
},
};
与工具集成
与Prettier集成
bash
npm install --save-dev eslint-config-prettier eslint-plugin-prettier prettier
javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:react/recommended',
'prettier', // 关闭与Prettier冲突的规则
],
plugins: ['prettier'],
rules: {
'prettier/prettier': 'error', // 启用Prettier作为ESLint规则
},
};
json
// .prettierrc
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2
}
与编辑器集成
json
// .vscode/settings.json
{
"eslint.packageManager": "npm",
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.formatOnSave": true
}
CI/CD集成
GitHub Actions配置
yaml
# .github/workflows/lint.yml
name: Lint
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x]
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npx eslint src/ --ext .js,.jsx,.ts,.tsx
- name: Run type check
run: npx tsc --noEmit
预提交钩子
json
// package.json
{
"scripts": {
"lint": "eslint src/ --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint src/ --ext .js,.jsx,.ts,.tsx --fix"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --cache --fix",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"pre-push": "npm run lint"
}
}
}
性能优化
缓存配置
javascript
// .eslintrc.js
module.exports = {
cache: true,
cacheLocation: '.eslintcache',
cacheStrategy: 'content',
// 其他配置...
};
排除不必要的文件
javascript
// .eslintrc.js
module.exports = {
ignorePatterns: [
'node_modules/',
'dist/',
'build/',
'coverage/',
'*.min.js',
'*.config.js',
'public/',
'.next/',
'.nuxt/',
],
// 或者使用单独的 .eslintignore 文件
};
并行处理
json
// package.json
{
"scripts": {
"lint:parallel": "npm-run-all --parallel lint:*",
"lint:client": "eslint src/client/",
"lint:server": "eslint src/server/",
"lint:shared": "eslint src/shared/"
}
}
规则设计原则
有意义的规则
javascript
// 好的规则:解决实际问题
module.exports = {
rules: {
'no-console': 'warn', // 防止生产环境的日志泄露
'no-debugger': 'error', // 防止调试代码上线
'eqeqeq': 'error', // 防止类型强制转换错误
},
};
// 避免过于严格的规则
module.exports = {
rules: {
// 避免:过于主观的规则
'max-len': 'off', // 如果团队认为这不重要
},
};
可维护的规则
javascript
// 使用可配置的规则
module.exports = {
rules: {
'max-lines-per-function': ['error', { max: 50, skipComments: true }],
'complexity': ['error', { max: 10 }],
},
};
文档和培训
规则文档
javascript
// .eslintrc.js - 添加注释说明规则目的
module.exports = {
rules: {
// 防止意外的全局变量污染
'no-implicit-globals': 'error',
// 确保变量在使用前已声明
'no-use-before-define': 'error',
// 防止内存泄漏
'no-unmodified-loop-condition': 'error',
},
};
团队培训
- 规则解释: 向团队解释每条规则的目的
- 工具使用: 培训如何使用ESLint工具
- 更新流程: 建立规则更新的流程
持续改进
定期审查
bash
# 定期运行命令检查规则效果
npx eslint --quiet src/ # 只显示错误,忽略警告
# 分析规则使用情况
npx eslint --print-config src/file.js | jq '.rules' > current-rules.json
渐进式改进
- 从ESLint推荐规则开始
- 根据项目需求逐步添加规则
- 定期评估规则的有效性
- 移除不再需要的规则
javascript
// 定期清理未使用的规则
module.exports = {
rules: {
// 定期检查这些规则是否仍然必要
'prefer-const': 'error',
'no-var': 'error',
// ...
},
};
通过遵循这些最佳实践,可以建立一个高效、可维护的ESLint配置,提高代码质量和团队开发效率。