第7章 7.2 工程化:ESLint + Prettier + Husky

上章回顾:上一章我们折腾了 Vite 的配置文件,学会了怎么自定义构建行为、优化开发体验。现在你的项目跑得挺欢了,但有个新问题冒出来了——

人多了一起写代码,问题就多了
- 张三用 Tab 缩进,李四用空格,项目打开一团糟
- 王五写了段 let a = 1;,赵六写了 const a: number = 1,谁对谁错?
- 每次 commit 之前,手动跑检查?太累了,忘了吧……

学完这章你能解决:代码规范混乱、每次提交前手动检查的繁琐、团队协作时代码风格不统一的问题。


1. 🎯 开场:想象一个没有"交通规则"的工地

想象你去一个建筑工地:
- 有人用锤子敲螺丝,有人用螺丝刀钉钉子
- 有人穿拖鞋进场,有人不戴安全帽
- 没有统一指挥,材料乱堆乱放

这样的工地,迟早要出事故。代码项目也一样——没有统一的规范,多人协作就是灾难。

ESLint、Prettier、Husky 就是代码工地的"交通规则"和"安全帽\n\nSimple tech illustration expla\n\nAI comic creation scene, creat\n\n":
- ESLint:检查代码有没有"违章"(语法错误、坏味道)
- Prettier:统一代码"长相"(缩进、换行、引号风格)
- Husky:每次"进场施工"前(git commit),强制检查一遍


2. 🧱 基础:三个工具各管什么?

2.1 ESLint——代码警察

是什么:一个代码检查工具,专门抓"坏代码"。

生活类比:就像驾校的考官,拿着打分表看你动作规不规范。压线了吗?闯红灯了吗?

为什么要用
- 提前发现潜在的 bug(比如写了 == 而不是 ===
- 强制团队遵守同一套代码规范
- 减少 code review 时因为格式问题吵架

怎么用(以 Vue3 + TypeScript 项目为例):

# 1. 先安装(如果还没装的话)
npm install eslint eslint-plugin-vue @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev

# 2. 创建配置文件 .eslintrc.cjs
// .eslintrc.cjs
module.exports = {
root: true,
parser: 'vue-eslint-parser',           // 解析 Vue 文件
parserOptions: {
parser: '@typescript-eslint/parser', // 解析 TypeScript
ecmaVersion: 2022,
sourceType: 'module',
},
extends: [
'plugin:vue/vue3-recommended',       // Vue3 官方规范
'plugin:@typescript-eslint/recommended', // TypeScript 推荐规范
],
rules: {
// 自定义规则:禁止 console.log
'no-console': 'warn',
// 自定义规则:强制使用单引号
'quotes': ['warn', 'single'],
// 关闭某些过于严格的规则
'@typescript-eslint/no-explicit-any': 'off',
},
}

解释:这个配置文件告诉 ESLint 要检查什么、用什么规则。张三写 console.log('hello'),ESLint 会警告:"嘿,禁止用 console.log!"

2.2 Prettier——代码美容师

是什么:一个代码格式化工具,把你的代码"美容"成统一的样子。

生活类比:就像整形医院,你给它一张照片,它还你一张完美自拍。甭管你原来长什么样,整完都一个样。

为什么要用
- ESLint 管"逻辑规范",Prettier 管"视觉规范"
- 两人分工,职责清晰
- 配置简单,效果立竿见影

怎么用

# 1. 安装
npm install prettier --save-dev

# 2. 创建配置文件 .prettierrc
// .prettierrc
{
"semi": true,           // 句末加分号
"singleQuote": true,    // 使用单引号
"tabWidth": 2,          // Tab 宽度 2 空格
"trailingComma": "all", // 尽可能尾随逗号
"printWidth": 80        // 一行最多 80 字符
}
// .prettierrc.js
module.exports = {
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'all',
printWidth: 80,
}

解释:配置完这个,你写的 const a=1 会被 Prettier 自动变成 const a = 1。这就是"美容"——统一、安全、好看。

2.3 Husky——Git 门口的保安

是什么:在 Git 操作(如 commit、push)之前,自动运行你指定脚本的工具。

生活类比:就像地铁安检,你进站之前必须过一遍安检机。危险品?别想进去!

为什么要用
- 强制在 commit 之前跑 ESLint + Prettier
- 防止"带病代码"进入代码库
- 自动化流程,不用依赖人工记忆

怎么用

# 1. 安装 Husky(需要先初始化 git 仓库)
npm install husky --save-dev

# 2. 初始化 Husky
npx husky install

# 3. 添加一个 pre-commit 钩子(在 commit 之前执行)
npx husky add .husky/pre-commit "npx eslint src/ --fix && npx prettier src/ --write"

# 4. 以后每次 git commit 都会自动跑 ESLint + Prettier

解释:加完这个钩子,你每次 git commit,Git 都会先跑一遍检查。如果 ESLint 发现问题,commit 会被拦截,代码进不去。

2.4 三者关系:一条流水线

你写代码 

git commit 

Husky 拦截("等一下,让我先检查")

ESLint 检查("这段代码规范吗?")

Prettier 美容("让我把你整漂亮")

检查通过 → 代码正式提交 ✅
检查失败 → commit 被拒 ❌

3. 🔥 实战:3 个递进小项目

项目 1:给现有 Vue 项目加上 ESLint 检查(5 分钟)

目标:体验 ESLint 怎么抓问题

步骤

# 在你的 Vue 项目里运行检查
npx eslint src/ --ext .vue,.ts,.js

假设你的 src/utils/format.ts 有这样一段代码:

// src/utils/format.ts
export function formatDate(date: any) {
// 注意:这里用了 any 类型,ESLint 会警告
return date.toLocaleDateString('zh-CN')
}

ESLint 输出:

/src/utils/format.ts
5:9  warning  Unexpected any. Specify a different type  @typescript-eslint/no-explicit-any

解释:ESLint 发现你用了 any 类型,警告你换成具体类型。这就是"代码警察"在干活。


项目 2:配置 Prettier + ESLint 联动(15 分钟)

目标:让两个工具配合工作,格式化后再检查

步骤 1:安装冲突解决插件

npm install eslint-config-prettier --save-dev

步骤 2:更新 .eslintrc.cjs,在 extends 里加上 Prettier

// .eslintrc.cjs
module.exports = {
root: true,
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2022,
sourceType: 'module',
},
extends: [
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',  // ← 加这一行,关掉和 Prettier 冲突的 ESLint 规则
],
rules: {
'no-console': 'warn',
'quotes': ['warn', 'single'],
'@typescript-eslint/no-explicit-any': 'off',
},
}

步骤 3:在 package.json 里加一条脚本

{
"scripts": {
"lint": "eslint src/ --ext .vue,.ts,.js",
"format": "prettier src/ --write",
"lint:fix": "eslint src/ --ext .vue,.ts,.js --fix && prettier src/ --write"
}
}

运行

# 格式化所有代码
npm run format

# 检查代码问题
npm run lint

# 一次性完成格式化和检查
npm run lint:fix

解释eslint --fix 会自动修复能修复的问题(比如引号、缩进),然后 Prettier 统一美化一遍。


项目 3:完整的 Git Hooks 自动化流程(15 分钟)

目标:实现"提交代码 → 自动检查 → 自动格式化 → 成功提交"一条龙

完整配置步骤

# 1. 初始化 Git 仓库(如果还没有)
git init

# 2. 安装所有需要的依赖
npm install -D eslint prettier eslint-plugin-vue @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-prettier husky lint-staged

# 3. 初始化 Husky
npx husky install

# 4. 创建 pre-commit 钩子
npx husky add .husky/pre-commit "npx lint-staged"

# 5. 在 package.json 里加 lint-staged 配置
{
"lint-staged": {
"*.{vue,ts,js}": [
  "eslint --fix",
  "prettier --write"
]
}
}

6. 在 .git/hooks/pre-commit 文件里写入

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged

使用流程

# 你修改了一些代码
echo "console.log('hello')" > src/test.ts

# 添加到暂存区
git add src/test.ts

# 提交(这时候 Husky 会自动拦截并检查)
git commit -m "feat: add test file"

# 输出类似:
# ✔ Linting 1 file(s)
# ✔ Formatting 1 file(s)
# [main abc1234] feat: add test file

解释:lint-staged 只检查你这次提交改的文件,不检查整个项目,速度快。Husky 保证每次提交前都必须过这一关。


4. 💪 进阶:常见坑 + 调试技巧

坑 1:ESLint 和 Prettier 规则冲突

❌ 错误示例:两个工具各自为政,ESLint 要求双引号,Prettier 要求单引号

// .eslintrc.cjs(没加 prettier 配置)
rules: {
'quotes': ['error', 'single'],  // ESLint 要单引号
}
// .prettierrc
singleQuote: false  // Prettier 要双引号

结果:两个工具打起来,代码被改来改去。

✅ 正确做法:在 ESLint 继承 Prettier 配置

// .eslintrc.cjs
extends: [
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',  // ← 这行要加在最后
],

坑 2:Husky 钩子没生效

❌ 错误:直接编辑 .husky/pre-commit,但没有给文件执行权限

# 直接写文件,但没有执行权限
echo "npx eslint src/ --fix" > .husky/pre-commit
git commit  # 不生效!

✅ 正确做法:用 husky add 命令添加钩子

# 自动创建文件并设置好权限
npx husky add .husky/pre-commit "npx eslint src/ --fix"
chmod +x .husky/pre-commit  # 保险起见再加个权限

坑 3:commit 的时候 ESLint 报错,但不知道是哪行

❌ 错误:直接看报错信息,找不到具体位置

src/utils/api.ts
某些错误

✅ 正确做法:加 --max-warnings=0 让警告也失败

npx eslint src/ --max-warnings=0

或者在 CI 环境下运行完整检查:

npm run lint
if [ $? -ne 0 ]; then
echo "ESLint 检查失败,请修复后再提交"
exit 1
fi

坑 4:大型项目 lint 速度太慢

❌ 错误:每次 commit 检查整个项目,等半天

✅ 正确做法:用 lint-staged 只检查改动的文件

// package.json
{
"lint-staged": {
"*.{vue,ts,js}": [
  "eslint --fix",
  "prettier --write"
]
}
}

坑 5:Windows 系统 Husky 不工作

❌ 错误:在 Windows 上 .husky/_/husky.sh 找不到

✅ 正确做法:Windows 用户用管理员权限的 PowerShell:

# 以管理员身份运行 PowerShell
Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned
npx husky install

调试技巧:VSCode 实时检查

安装 VSCode 插件 ESLintPrettier,保存文件时自动检查和格式化:

// .vscode/settings.json
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

效果:你敲代码的时候,VSCode 实时显示红色的错误波浪线,一保存就自动修复。


5. ✏️ 练习题

练习 1(1 分钟):认识 ESLint 输出

  • 输入:你运行 npx eslint src/App.vue
  • 输出:显示 1 error, 2 warnings
  • 提示--max-warnings=0 可以把警告当错误处理

练习 2(2 分钟):给规则加个开关

  • 输入:在 .eslintrc.cjs 里把 no-consolewarn 改成 error
  • 预期输出:再运行 npm run lint,console.log 会导致失败
  • 提示:规则值可以是 'off''warn''error'

练习 3(3 分钟):配置 Prettier 尾随逗号

  • 输入:把 .prettierrc 改成 "trailingComma": "none"
  • 预期输出:格式化后 const obj = { a: 1 }(对象后面没逗号)
  • 提示"all" 会尽可能加尾随逗号

练习 4(5 分钟):把两个工具串起来

  • 输入:在 package.json 里写一个 dev:fix 脚本,先跑 ESLint 再跑 Prettier
  • 预期输出npm run dev:fix 能一次性完成检查和格式化
  • 提示:脚本可以用 && 连接两个命令

练习 5(5 分钟):分析报错截图(模拟)

  • 输入:Husky 拦截了 commit,报错 Cannot find module 'eslint'
  • 预期输出:说出原因并修复
  • 提示:检查依赖有没有装,或者用 npx 代替直接调用

作业:做一个「代码规范自动化工具」

需求描述:为一个小型 Vue3 项目配置完整的代码规范流程

功能点
1. 配置 ESLint + TypeScript + Vue3 规则
2. 配置 Prettier 格式化规则
3. 配置 Husky + lint-staged 自动化流程
4. 写一个使用说明 CONTRIBUTING.md,告诉队友怎么用

加分项
1. 配置一个 commitlint 规范提交信息格式(如 feat:fix:
2. 配置 GitHub Actions CI,在 PR 时自动跑检查

验收标准
- 能跑 git commit 且自动触发检查
- ESLint 和 Prettier 冲突时报错
- 提交信息不符合规范时 commit 被拒


6. 📚 总结 + 资源

本文学了 3 件事
1. ESLint 是代码警察,管"逻辑规范"
2. Prettier 是美容师,管"视觉规范"
3. Husky 是门口的保安,保证"进场前必须过安检"

延伸资源
- ESLint 官方文档(英文,但例子清晰)
- Prettier 官方文档(配置项最全)
- Husky GitHub 仓库(更新频繁,Windows 兼容性说明很有用)

互动钩子:你在团队项目里被 ESLint 拦截过吗?当时是因为什么规则?评论区聊聊,老粉优先回复!


下章预告:下一章我们要解决一个更复杂的问题——当项目越来越大,里面有好多好多子项目的时候,怎么管理?pnpm workspace 就是答案……

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。