Appearance
Prettier与ESLint集成
Prettier和ESLint是两个不同的工具,各自解决不同的问题。Prettier专注于代码格式化,而ESLint专注于代码质量问题。将它们集成在一起可以提供完整的代码质量解决方案。
为什么需要集成
Prettier vs ESLint
| 工具 | 专注点 | 主要功能 |
|---|---|---|
| Prettier | 代码格式 | 缩进、引号、分号、括号等 |
| ESLint | 代码质量 | 潜在错误、最佳实践、代码风格 |
集成的好处
- 统一代码风格 - 确保团队代码风格一致
- 减少配置冲突 - 避免两种工具的规则冲突
- 提高开发效率 - 自动格式化和质量检查
- 减少代码审查争论 - 格式问题自动修复
基础集成
安装依赖
bash
npm install --save-dev eslint-config-prettier eslint-plugin-prettier
配置ESLint
javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended', // ESLint推荐规则
'plugin:prettier/recommended', // 启用prettier规则
],
plugins: ['prettier'],
rules: {
'prettier/prettier': 'error', // 将格式问题作为错误
},
};
Prettier配置
json
// .prettierrc
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"arrowParens": "avoid"
}
高级集成配置
使用eslint-config-prettier
eslint-config-prettier会关闭所有与Prettier冲突的ESLint规则:
javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'prettier', // 关闭与Prettier冲突的规则
'plugin:prettier/recommended', // 启用prettier推荐配置
],
plugins: ['prettier'],
rules: {
'prettier/prettier': [
'error',
{
'singleQuote': true,
'trailingComma': 'es5',
'printWidth': 80,
},
],
},
};
针对不同文件类型的配置
javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'prettier',
'plugin:prettier/recommended',
],
overrides: [
{
files: ['*.ts', '*.tsx'],
extends: [
'@typescript-eslint/recommended',
'prettier', // 确保关闭与Prettier的TypeScript相关冲突规则
],
},
{
files: ['*.vue'],
extends: [
'plugin:vue/vue3-essential',
'prettier',
],
},
],
};
框架特定集成
React项目集成
javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'prettier',
'plugin:prettier/recommended',
],
plugins: [
'react',
'prettier',
],
rules: {
'prettier/prettier': 'error',
'react/react-in-jsx-scope': 'off', // React 17+
},
settings: {
react: {
version: 'detect',
},
},
};
TypeScript项目集成
javascript
// .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'prettier',
'plugin:prettier/recommended',
],
plugins: [
'@typescript-eslint',
'prettier',
],
rules: {
'prettier/prettier': 'error',
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
},
};
Vue.js项目集成
javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:vue/vue3-essential',
'prettier',
'plugin:prettier/recommended',
],
plugins: [
'vue',
'prettier',
],
rules: {
'prettier/prettier': 'error',
'vue/html-self-closing': 'off', // 可根据团队偏好调整
},
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020,
sourceType: 'module',
},
};
编辑器配置
VS Code配置
json
// .vscode/settings.json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"eslint.format.enable": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.prettier": true
},
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"json",
"markdown"
]
}
统一格式化配置
json
// package.json
{
"scripts": {
"format": "prettier --write .",
"lint": "eslint src/ --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint src/ --ext .js,.jsx,.ts,.tsx --fix"
},
"lint-staged": {
"*.{js,jsx,ts,tsx,json,css,md}": [
"prettier --write",
"eslint --fix",
"git add"
]
}
}
CI/CD集成
GitHub Actions配置
yaml
# .github/workflows/format.yml
name: Format Check
on: [push, pull_request]
jobs:
prettier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Run Prettier check
run: npx prettier --check "**/*.{js,jsx,ts,tsx,json,css,md}"
eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npx eslint src/ --ext .js,.jsx,.ts,.tsx --max-warnings 0
常见问题和解决方案
1. 规则冲突
问题: ESLint和Prettier规则冲突
解决方案:
javascript
// 确保使用eslint-config-prettier
module.exports = {
extends: [
'eslint:recommended',
'prettier', // 这会关闭冲突的规则
],
};
2. 性能问题
问题: 同时运行ESLint和Prettier导致性能下降
解决方案:
json
// package.json
{
"scripts": {
// 先格式化再检查
"lint": "npm run format && eslint src/",
"lint:fast": "eslint src/ --cache" // 使用缓存
}
}
3. 配置复杂性
问题: 配置文件变得复杂
解决方案: 使用预设配置
javascript
// .eslintrc.js
module.exports = {
extends: [
'@company/eslint-config', // 使用公司共享配置
'prettier', // 集成Prettier
],
};
高级配置技巧
条件启用Prettier
javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
process.env.CI ? 'prettier' : 'plugin:prettier/recommended',
],
rules: {
'prettier/prettier': process.env.CI ? 'off' : 'error',
},
};
项目特定覆盖
javascript
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'prettier',
'plugin:prettier/recommended',
],
overrides: [
{
files: ['**/*.test.{js,ts}'],
rules: {
'prettier/prettier': 'warn', // 测试文件只警告
},
},
],
};
最佳实践
1. 统一工作流程
bash
# 推荐的工作流程
1. 代码编写
2. 保存时自动格式化 (Prettier)
3. 保存时自动修复 (ESLint)
4. 提交前全面检查
2. 团队配置
javascript
// 共享配置包
// @company/eslint-config-prettier/index.js
module.exports = {
extends: [
'eslint:recommended',
'prettier',
'plugin:prettier/recommended',
],
plugins: ['prettier'],
rules: {
'prettier/prettier': 'error',
},
};
3. 渐进式采用
javascript
// 逐步集成
// 阶段1: 只使用Prettier
// 阶段2: 添加ESLint基础规则
// 阶段3: 集成Prettier和ESLint
// 阶段4: 添加框架特定规则
通过正确集成Prettier和ESLint,可以建立一个强大的代码质量保证体系,既保证代码格式的一致性,又确保代码质量。