
在现代前端开发中,代码规范不仅仅是"好看"的问题,它关系到:
统计数据显示:
- 规范化的代码可以减少 40% 的 bug 率
- 团队协作效率提升 30%
- 代码审查时间减少 50%ESLint 是一个开源的 JavaScript 代码检查工具,用于识别和报告代码中的模式匹配问题。
# 全局安装
npm install -g eslint
# 项目本地安装(推荐)
npm install --save-dev eslint
# 使用 yarn
yarn add --dev eslint
# 使用 pnpm
pnpm add -D eslint# 交互式初始化
npx eslint --init
# 或者使用
npm init @eslint/config创建 .eslintrc.js 文件:
module.exports = {
// 环境配置
env: {
browser: true,
es2021: true,
node: true,
jest: true
},
// 继承的配置
extends: [
'eslint:recommended',
'@typescript-eslint/recommended'
],
// 解析器配置
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: {
jsx: true
}
},
// 插件
plugins: [
'@typescript-eslint',
'react',
'react-hooks'
],
// 自定义规则
rules: {
// 基础规则
'no-console': 'warn',
'no-debugger': 'error',
'no-unused-vars': 'error',
// 代码风格
'indent': ['error', 2],
'quotes': ['error', 'single'],
'semi': ['error', 'always'],
// React 相关
'react/jsx-uses-react': 'error',
'react/jsx-uses-vars': 'error',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn'
},
// 忽略配置
ignorePatterns: [
'dist/',
'build/',
'node_modules/',
'*.min.js'
]
};module.exports = {
rules: {
// 错误级别:off/0, warn/1, error/2
// 变量相关
'no-undef': 'error',
'no-unused-vars': ['error', {
vars: 'all',
args: 'after-used',
ignoreRestSiblings: false
}],
// 代码质量
'complexity': ['warn', 10],
'max-depth': ['warn', 4],
'max-lines': ['warn', 300],
'max-params': ['warn', 4],
// 最佳实践
'eqeqeq': ['error', 'always'],
'no-eval': 'error',
'no-implied-eval': 'error',
'prefer-const': 'error',
'no-var': 'error',
// ES6+ 特性
'arrow-spacing': 'error',
'prefer-arrow-callback': 'error',
'prefer-template': 'error'
}
};module.exports = {
plugins: [
// TypeScript 支持
'@typescript-eslint',
// React 支持
'react',
'react-hooks',
// Vue 支持
'vue',
// 导入检查
'import',
// JSX a11y
'jsx-a11y',
// 安全检查
'security'
],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:import/recommended',
'plugin:jsx-a11y/recommended',
'plugin:security/recommended'
]
};module.exports = {
// 覆盖配置
overrides: [
{
// 测试文件配置
files: ['**/*.test.js', '**/*.spec.js'],
env: {
jest: true
},
rules: {
'no-console': 'off'
}
},
{
// TypeScript 文件配置
files: ['**/*.ts', '**/*.tsx'],
parser: '@typescript-eslint/parser',
rules: {
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'warn'
}
}
]
};Prettier 是一个代码格式化工具,支持多种语言,能够自动格式化代码以保持一致的风格。
# 项目本地安装
npm install --save-dev prettier
# 使用 yarn
yarn add --dev prettier
# 使用 pnpm
pnpm add -D prettier创建 .prettierrc.js 文件:
module.exports = {
// 基础配置
printWidth: 80, // 每行最大字符数
tabWidth: 2, // 缩进空格数
useTabs: false, // 使用空格而不是 tab
semi: true, // 语句末尾添加分号
singleQuote: true, // 使用单引号
quoteProps: 'as-needed', // 对象属性引号
// JSX 配置
jsxSingleQuote: true, // JSX 中使用单引号
jsxBracketSameLine: false, // JSX 标签闭合位置
// 数组和对象
trailingComma: 'es5', // 尾随逗号
bracketSpacing: true, // 对象字面量空格
// 箭头函数
arrowParens: 'avoid', // 箭头函数参数括号
// 其他
endOfLine: 'lf', // 换行符
embeddedLanguageFormatting: 'auto', // 嵌入语言格式化
// HTML 配置
htmlWhitespaceSensitivity: 'css',
// Vue 配置
vueIndentScriptAndStyle: false
};创建 .prettierignore 文件:
# 依赖
node_modules/
package-lock.json
yarn.lock
pnpm-lock.yaml
# 构建产物
dist/
build/
coverage/
# 配置文件
.env
.env.local
.env.production
# 其他
*.min.js
*.min.css
public/module.exports = {
// 全局配置
printWidth: 80,
tabWidth: 2,
// 覆盖配置
overrides: [
{
files: '*.json',
options: {
tabWidth: 4
}
},
{
files: '*.md',
options: {
printWidth: 100,
proseWrap: 'always'
}
},
{
files: '*.{css,scss,less}',
options: {
singleQuote: false
}
}
]
};VS Code 配置 (.vscode/settings.json):
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}WebStorm 配置:
ESLint 和 Prettier 在某些规则上可能存在冲突,需要正确配置来避免。
# 安装 eslint-config-prettier(禁用冲突规则)
npm install --save-dev eslint-config-prettier
# 安装 eslint-plugin-prettier(将 Prettier 作为 ESLint 规则运行)
npm install --save-dev eslint-plugin-prettier更新 .eslintrc.js:
module.exports = {
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:prettier/recommended', // 必须放在最后
],
plugins: [
'@typescript-eslint',
'react',
'prettier'
],
rules: {
// Prettier 相关
'prettier/prettier': 'error',
// 禁用与 Prettier 冲突的规则
'indent': 'off',
'quotes': 'off',
'semi': 'off',
'comma-dangle': 'off',
'max-len': 'off',
// 保留非格式化相关的规则
'no-console': 'warn',
'no-debugger': 'error',
'no-unused-vars': 'error'
}
};创建 prettier-eslint 配置:
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'prettier' // 禁用所有与 Prettier 冲突的规则
],
plugins: ['prettier'],
rules: {
'prettier/prettier': [
'error',
{
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: true,
trailingComma: 'es5',
bracketSpacing: true,
arrowParens: 'avoid'
}
]
}
};{
"scripts": {
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css,md}\"",
"format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx,json,css,md}\"",
"code-check": "npm run lint && npm run format:check",
"code-fix": "npm run lint:fix && npm run format"
}
}创建 scripts/code-quality.js:
const { execSync } = require('child_process');
const chalk = require('chalk');
function runCommand(command, description) {
console.log(chalk.blue(`🔍 ${description}...`));
try {
execSync(command, { stdio: 'inherit' });
console.log(chalk.green(`✅ ${description} 完成`));
} catch (error) {
console.log(chalk.red(`❌ ${description} 失败`));
process.exit(1);
}
}
// 代码质量检查流程
console.log(chalk.yellow('🚀 开始代码质量检查...'));
runCommand('npm run lint', 'ESLint 检查');
runCommand('npm run format:check', 'Prettier 格式检查');
runCommand('npm run test', '单元测试');
console.log(chalk.green('🎉 所有检查通过!'));安装和配置:
# 安装 husky
npm install --save-dev husky
# 安装 lint-staged
npm install --save-dev lint-staged
# 初始化 husky
npx husky install
# 添加 pre-commit hook
npx husky add .husky/pre-commit "npx lint-staged"配置 package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write",
"git add"
],
"*.{json,css,md}": [
"prettier --write",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
}.husky/pre-commit:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo "🔍 Running pre-commit checks..."
# 运行 lint-staged
npx lint-staged
# 运行类型检查
npm run type-check
# 运行测试
npm run test:staged
echo "✅ Pre-commit checks passed!".husky/commit-msg:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# 提交信息规范检查
npx commitlint --edit $1创建 .github/workflows/code-quality.yml:
name: Code Quality Check
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
code-quality:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x]
steps:
- name: Checkout code
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: npm run lint
- name: Check Prettier formatting
run: npm run format:check
- name: Run type check
run: npm run type-check
- name: Run tests
run: npm run test:coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info创建 .gitlab-ci.yml:
stages:
- quality
- test
- build
variables:
NODE_VERSION: "18"
cache:
paths:
- node_modules/
before_script:
- npm ci
lint:
stage: quality
script:
- npm run lint
only:
- merge_requests
- main
format-check:
stage: quality
script:
- npm run format:check
only:
- merge_requests
- main
type-check:
stage: quality
script:
- npm run type-check
only:
- merge_requests
- main
test:
stage: test
script:
- npm run test:coverage
coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml创建 .editorconfig:
# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.{js,jsx,ts,tsx,vue}]
indent_size = 2
[*.{json,yml,yaml}]
indent_size = 2
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab创建 .vscode/settings.json:
{
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.formatOnType": false,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.organizeImports": true
},
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue"
],
"typescript.preferences.importModuleSpecifier": "relative",
"javascript.preferences.importModuleSpecifier": "relative",
"files.associations": {
"*.css": "css",
"*.scss": "scss"
},
"emmet.includeLanguages": {
"javascript": "javascriptreact",
"typescript": "typescriptreact"
}
}创建 .vscode/extensions.json:
{
"recommendations": [
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"bradlc.vscode-tailwindcss",
"ms-vscode.vscode-typescript-next"
]
}npm install --save-dev \
eslint \
prettier \
@typescript-eslint/parser \
@typescript-eslint/eslint-plugin \
eslint-plugin-react \
eslint-plugin-react-hooks \
eslint-plugin-jsx-a11y \
eslint-config-prettier \
eslint-plugin-prettier.eslintrc.js:
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: [
'react',
'react-hooks',
'@typescript-eslint',
'jsx-a11y',
'prettier'
],
rules: {
'prettier/prettier': 'error',
// React 相关
'react/react-in-jsx-scope': 'off', // React 17+
'react/prop-types': 'off', // 使用 TypeScript
'react/jsx-props-no-spreading': 'warn',
'react/jsx-key': 'error',
// React Hooks
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
// TypeScript
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
// 可访问性
'jsx-a11y/anchor-is-valid': 'warn',
'jsx-a11y/click-events-have-key-events': 'warn'
},
settings: {
react: {
version: 'detect'
}
}
};.prettierrc.js:
module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: true,
quoteProps: 'as-needed',
jsxSingleQuote: true,
trailingComma: 'es5',
bracketSpacing: true,
jsxBracketSameLine: false,
arrowParens: 'avoid',
endOfLine: 'lf'
};npm install --save-dev \
eslint \
prettier \
@typescript-eslint/parser \
@typescript-eslint/eslint-plugin \
eslint-plugin-vue \
@vue/eslint-config-typescript \
@vue/eslint-config-prettier \
eslint-config-prettier \
eslint-plugin-prettier.eslintrc.js:
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:vue/vue3-recommended',
'@vue/typescript/recommended',
'prettier'
],
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: [
'vue',
'@typescript-eslint',
'prettier'
],
rules: {
'prettier/prettier': 'error',
// Vue 相关
'vue/multi-word-component-names': 'off',
'vue/no-v-html': 'warn',
'vue/require-default-prop': 'error',
'vue/require-prop-types': 'error',
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
// TypeScript
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'off'
}
};.eslintrc.js:
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'@typescript-eslint/recommended-requiring-type-checking',
'prettier'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: './tsconfig.json'
},
plugins: [
'@typescript-eslint',
'prettier'
],
rules: {
'prettier/prettier': 'error',
// TypeScript 严格规则
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'warn',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
// 命名规范
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'interface',
format: ['PascalCase'],
prefix: ['I']
},
{
selector: 'typeAlias',
format: ['PascalCase']
},
{
selector: 'enum',
format: ['PascalCase']
}
]
}
};.eslintrc.js:
module.exports = {
env: {
node: true,
es2021: true
},
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:security/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: [
'@typescript-eslint',
'security',
'prettier'
],
rules: {
'prettier/prettier': 'error',
// Node.js 相关
'no-console': 'off', // 服务端允许 console
'no-process-exit': 'error',
// 安全相关
'security/detect-object-injection': 'warn',
'security/detect-non-literal-fs-filename': 'warn',
// TypeScript
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'warn'
}
};症状:
error Delete `⏎` prettier/prettier
error Expected indentation of 2 spaces but found 4 indent解决方案:
eslint-config-prettiermodule.exports = {
extends: [
'eslint:recommended',
'prettier' // 必须放在最后
]
};症状:团队成员保存文件时格式化结果不同
解决方案:
// .vscode/settings.json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.configPath": "./.prettierrc.js"
}# .editorconfig
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true症状:提交代码时没有触发代码检查
解决方案:
# 重新安装 husky
npm uninstall husky
npm install --save-dev husky
npx husky installchmod +x .husky/pre-commit# 测试 pre-commit hook
npx husky run pre-commit症状:ESLint 检查速度很慢
解决方案:
{
"scripts": {
"lint": "eslint --cache --cache-location .eslintcache src"
}
}// .eslintrc.js
module.exports = {
ignorePatterns: [
'dist/',
'build/',
'node_modules/',
'*.min.js',
'coverage/'
]
};npm install --save-dev eslint-parallel症状:TypeScript 文件 ESLint 检查报错
解决方案:
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname
}
};{
"include": [
"src/**/*",
"tests/**/*"
]
}npm ls eslint prettiernpx eslint --print-config src/index.jsnpx eslint --no-eslintrc --config .eslintrc.js src/npx prettier --check src/# 检查 ESLint 配置
npx eslint --debug src/
# 检查 Prettier 配置
npx prettier --check --debug-check src/
# 清除缓存
rm -rf .eslintcache
rm -rf node_modules/.cache
# 重新安装依赖
rm -rf node_modules package-lock.json
npm install第一阶段:基础配置
// .eslintrc.js - 初始配置
module.exports = {
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'prettier'
],
rules: {
// 渐进式规则,从警告开始
'@typescript-eslint/no-explicit-any': 'warn',
'react/prop-types': 'off',
'no-console': 'warn'
}
};第二阶段:严格化规则
// 3个月后升级配置
module.exports = {
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'@typescript-eslint/recommended-requiring-type-checking',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'prettier'
],
rules: {
// 升级为错误级别
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/explicit-function-return-type': 'warn',
'react/jsx-key': 'error',
'jsx-a11y/alt-text': 'error'
}
};效果统计:
严格的代码质量要求:
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:vue/vue3-recommended',
'@vue/typescript/recommended',
'prettier'
],
rules: {
// 组件库特殊要求
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
'vue/require-default-prop': 'error',
'vue/require-prop-types': 'error',
'vue/no-v-html': 'error', // 安全考虑
// 文档要求
'jsdoc/require-description': 'error',
'jsdoc/require-param': 'error',
'jsdoc/require-returns': 'error'
}
};自动化文档生成:
{
"scripts": {
"docs:lint": "eslint docs --ext .js,.vue",
"docs:format": "prettier --write docs/**/*.{js,vue,md}",
"build:docs": "npm run docs:lint && npm run docs:format && vitepress build docs"
}
}基础配置包:
// packages/eslint-config-micro-frontend/index.js
module.exports = {
extends: [
'eslint:recommended',
'prettier'
],
env: {
browser: true,
es2021: true
},
rules: {
// 微前端特殊规则
'no-undef': 'error', // 防止全局变量污染
'no-implicit-globals': 'error',
// 命名规范
'camelcase': ['error', {
properties: 'never',
ignoreGlobals: true
}]
},
overrides: [
{
files: ['**/*.react.{js,jsx,ts,tsx}'],
extends: ['plugin:react/recommended']
},
{
files: ['**/*.vue'],
extends: ['plugin:vue/vue3-recommended']
}
]
};子应用配置:
// 子应用 .eslintrc.js
module.exports = {
extends: [
'@company/eslint-config-micro-frontend',
'@company/eslint-config-micro-frontend/react' // 或 vue
],
rules: {
// 子应用特定规则
}
};量化指标:
团队反馈:
ESLint + Prettier 的组合为前端项目提供了强大的代码质量保障。通过合理的配置和工作流集成,可以显著提升团队的开发效率和代码质量。
eslint-config-prettier 避免规则冲突通过系统性的代码规范实施,您的团队将获得更高的开发效率、更好的代码质量和更愉快的协作体验。
本文档将持续更新,欢迎提供反馈和建议。