代码规范与质量
# 04.代码规范与质量
ESLint 查 bug,Prettier 管格式,Husky 守提交——构建"写代码时自动发现、提交前强制拦截"的质量防线。
# 1. 案例引入:一个没有规范的项目长什么样
src/
userService.ts # 缩进:2 空格
order_service.ts # 缩进:Tab
product-service.ts # 命名:kebab-case
paymentService.ts # 命名:camelCase
LoginView.vue # 命名:PascalCase
loginView.vue # 与上面同名?Linux 区分大小写,Mac 不区分!
# 结果:
# 1. Code Review 60% 时间在争论格式问题
# 2. 新人:不知道变量该用 const 还是 let
# 3. PR:某次不小心提交了 debugger + console.log
# 4. 合并后:发现 api 拼成了 aip——线上请求全部 404
# 这些都不应该是人脑检查的——应该由工具自动拦截!
# 2. 三层质量防线
第一层:写代码时(Real-time)
├── ESLint ← 编辑器插件实时提示(红色/黄色下划线)
└── TypeScript ← 类型错误实时提示
第二层:提交前(Pre-commit)
├── Husky + lint-staged ← git commit 触发
└── 只检查和格式化暂存区的文件(快!)
第三层:CI / 代码审查
├── GitHub Actions / Jenkins ← npm run lint + npm test
└── SonarQube ← 代码质量扫描
# 3. ESLint:代码质量检查
# 3.1 核心概念
ESLint 不是"格式化工具"——它是"查 bug 和 bad practice 的工具"
ESLint 做什么:
✅ 未使用的变量 no-unused-vars
✅ console.log 遗留 no-console
✅ 使用 var 而非 const/let no-var
✅ 未处理的 Promise no-floating-promises
✅ 循环引用 import/no-cycle
✅ 文件名与导出不一致 filenames/match-exported
Prettier 做什么:
✅ 缩进 2 空格 vs 4 空格
✅ 单引号 vs 双引号
✅ 行尾要不要分号
✅ 最大行宽
# 3.2 Vue 3 + TS 项目推荐配置
npm install -D eslint @vue/eslint-config-typescript eslint-plugin-vue
// .eslintrc.cjs
module.exports = {
root: true,
env: {
browser: true,
node: true,
es2021: true
},
extends: [
'plugin:vue/vue3-recommended', // Vue 3 最佳实践
'eslint:recommended', // ESLint 推荐规则
'@vue/eslint-config-typescript', // TypeScript 支持
'@vue/eslint-config-prettier' // 关闭与 Prettier 冲突的规则(必须放最后)
],
parserOptions: {
ecmaVersion: 'latest'
},
rules: {
// 宽松规则
'vue/multi-word-component-names': 'off', // 允许单名单词组件名
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 严格规则
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'vue/no-unused-vars': 'error',
'vue/component-tags-order': ['error', {
order: ['script', 'template', 'style']
}]
}
}
# 3.3 常用规则分类速查
| 分类 | 规则举例 | 级别 |
|---|---|---|
| 潜在错误 | no-debugger, no-unreachable | error |
| 最佳实践 | no-var, prefer-const, eqeqeq | warn/error |
| Vue | vue/no-mutating-props, vue/require-prop-types | error |
| TypeScript | @typescript-eslint/no-explicit-any | warn |
| 导入 | import/no-cycle, import/no-duplicates | error |
# 4. Prettier:代码格式化
# 4.1 安装与配置
npm install -D prettier @vue/eslint-config-prettier
// .prettierrc
{
"semi": false, // 不要分号
"singleQuote": true, // 单引号
"trailingComma": "none", // 尾逗号:无
"printWidth": 100, // 最大行宽
"tabWidth": 2, // 缩进宽度
"arrowParens": "avoid", // 箭头函数单参数省略括号
"bracketSpacing": true, // { foo } 而非 {foo}
"vueIndentScriptAndStyle": true // Vue 脚本和样式缩进
}
# 4.2 ESLint + Prettier 分工口诀
ESLint: 代码"对不对" → 查逻辑问题、潜在 bug
Prettier: 代码"美不美" → 管缩进、引号、换行
两者不冲突的关键:
@vue/eslint-config-prettier → 关闭 ESLint 中所有格式相关规则
eslint-plugin-prettier → Prettier 的格式问题作为 ESLint 错误(可选)
# 5. Husky + lint-staged:Git 门禁
# 5.1 为什么需要 Git Hooks
如果没有 Husky:
开发者 push → Code Review → 发现 12 个格式问题 → 修改 → 重新 Review
有了 Husky + lint-staged:
git commit → 自动 ESLint 修复 → 自动 Prettier 格式化
↓ 有错误
commit 中断(强制修复后才可提交)
# 5.2 配置
npm install -D husky lint-staged
npx husky init # 自动创建 .husky/pre-commit
// package.json (或 .lintstagedrc.json)
{
"lint-staged": {
"*.{ts,tsx,vue}": [
"eslint --fix",
"prettier --write"
],
"*.{css,scss}": [
"prettier --write"
]
}
}
# .husky/pre-commit
npx lint-staged
# 5.3 Commitlint:规范提交信息
npm install -D @commitlint/cli @commitlint/config-conventional
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional']
}
提交信息规范:
feat: 新增缓存机制 # 新功能
fix: 修复登录超时问题 # Bug 修复
docs: 更新 API 文档 # 文档
style: 格式化代码 # 格式(不影响逻辑)
refactor: 重构用户服务 # 重构
test: 添加登录单元测试 # 测试
chore: 升级依赖版本 # 构建/工具
格式:type(scope?): subject
# 6. TypeScript 严格模式
{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}
TS 严格模式在 CI 中的使用:
# 开发阶段:用 IDE 的实时 TS 检查,构建时跳过类型检查(Vite 默认行为)
npm run dev
# 提交前/CI 中:专门做一次完整的类型检查
npx tsc --noEmit # 只检查不输出,耗时 5~20 秒
# 7. 测试基础:Jest / Vitest
# 7.1 Vitest(Vite 原生测试框架)
npm install -D vitest @vue/test-utils happy-dom
// vitest.config.ts
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
environment: 'happy-dom', // 模拟 DOM 环境
include: ['src/**/*.{test,spec}.{ts,tsx}']
}
});
// src/composables/__tests__/useCounter.spec.ts
import { describe, it, expect } from 'vitest'
import { useCounter } from '../useCounter'
describe('useCounter', () => {
it('should increment', () => {
const { count, increment } = useCounter(0)
expect(count.value).toBe(0)
increment()
expect(count.value).toBe(1)
})
})
# 7.2 测试金字塔
┌────────┐
│ E2E │ 少量——Playwright / Cypress
│ 5% │ 完整用户流程
┌┴────────┴┐
│ 集成测试 │ 中等——组件交互测试
│ 15% │
┌┴──────────┴┐
│ 单元测试 │ 大量——函数/Composable
│ 80% │ 快速运行,覆盖核心逻辑
└────────────┘
# 8. 实战:完整质量体系配置
# 初始化项目质量工具链
npm install -D \
eslint @vue/eslint-config-typescript eslint-plugin-vue \
prettier @vue/eslint-config-prettier \
husky lint-staged @commitlint/cli @commitlint/config-conventional \
vitest @vue/test-utils happy-dom
# 一键检查和格式化
npm run lint # eslint --ext .ts,.vue src/
npm run format # prettier --write "src/**/*.{ts,vue,css}"
npm run test # vitest run
npm run check # tsc --noEmit
最终效果:
git commit -m "feat: 添加用户头像上传"
↓
Husky 触发 pre-commit
↓
lint-staged 只处理暂存区文件
├── ESLint --fix (检查+自动修复)
└── Prettier --write (统一格式)
↓
全部通过 → 提交成功 ✅
# 9. 速查表
| 工具 | 用途 | 关键命令 |
|---|---|---|
| ESLint | 代码质量(查bug) | eslint --fix src/ |
| Prettier | 代码格式 | prettier --write src/ |
| Husky | Git 钩子 | .husky/pre-commit |
| lint-staged | 只检查暂存文件 | npx lint-staged |
| commitlint | 提交信息规范 | commitlint.config.js |
| TS strict | 类型严格检查 | tsc --noEmit |
| Vitest | 单元/集成测试 | vitest run |
质量保障三原则:
- 能自动化的绝不人工(ESLint/Prettier/Husky)
- 能在提交前拦住的绝不流入 PR(lint-staged)
- 类型检查 = 最低成本的 bug 预防(strict: true)
下一篇:05.前端性能优化
上次更新: 2026/06/24, 14:17:21