第84课:代码规范:ESLint + Prettier——配置、规则、与编辑器集成、lint-staged + Husky
高质量的代码不仅在功能上正确,还应该在风格一致、低错误风险和可维护性上达到团队标准。手动审查代码风格既低效又不可靠,因此前端工程化体系引入了两类自动化工具:ESLint 负责代码质量检查与潜在错误发现(逻辑错误、未使用的变量、不安全写法),Prettier 负责代码格式化(缩进、引号、分号等风格统一)。两者分工明确,配合使用可以大幅减少 Code Review 中的风格争议,让团队专注于逻辑和架构。本节课将系统讲解 ESLint 的配置体系、规则集与共享配置、Prettier 的选项与最佳实践、两者集成时冲突的解决,以及通过 Husky 和 lint-staged 在 Git 提交前自动执行检查的完整工作流。
1. ESLint 概述与核心价值
ESLint 是 JavaScript 生态中最主流的静态代码分析工具。它在不执行代码的情况下分析源码,根据可配置的规则集检测潜在问题——包括语法错误、最佳实践偏离、潜在 Bug 以及风格不一致。
ESLint 的核心特征:
- 可完全配置:每条规则都可以设为
off/warn/error,并支持自定义参数。 - 插件化架构:通过插件扩展对 TypeScript、Vue、React、JSX 等语法的支持。
- 自动修复:很多规则支持
--fix,自动修复代码风格问题。 - 共享配置:社区提供了大量预设规则集(
eslint:recommended、airbnb、standard),开箱即用。
1.1 快速初始化
1 | npm init @eslint/config |
该向导会询问项目类型、框架、使用的模块系统、是否使用 TypeScript 等,并生成对应的 .eslintrc 配置文件。
1.2 配置文件格式
ESLint 支持多种配置文件格式(按优先级从高到低):.eslintrc.js、.eslintrc.cjs、.eslintrc.yaml、.eslintrc.json、package.json 中的 eslintConfig 字段。**推荐使用 .eslintrc.js**(或 .eslintrc.cjs),因为它支持注释和动态配置,灵活性最高。
2. ESLint 配置体系详解
一个典型的 ESLint 配置文件包含以下顶层字段:
1 | // .eslintrc.js |
2.1 env:声明运行环境
env 告诉 ESLint 代码将在哪些环境中运行,从而允许使用对应环境的全局变量而不会触发 no-undef 规则。
| 环境变量 | 允许的全局对象 |
|---|---|
browser |
window、document、localStorage 等 |
node |
process、require、module、__dirname |
es2022 |
允许 ES2022 语法及全局变量 |
jest |
describe、it、expect 等测试全局变量 |
jquery |
$、jQuery |
2.2 parserOptions:解析器选项
parserOptions 配置 ESLint 如何解析 JavaScript 语法。注意:它仅控制语法解析,不控制哪些全局变量可用(后者由 env 控制)。
ecmaVersion: 'latest'总是启用最新 ES 语法。sourceType: 'module'启用import/export语法。ecmaFeatures.jsx: true启用 JSX 解析。
如果需要解析 TypeScript,需要安装 @typescript-eslint/parser 并将其设为 parser:
1 | module.exports = { |
2.3 rules:规则配置
每条规则的值可以是:
'off'或0:关闭规则。'warn'或1:违反时发出警告(不阻止 CI)。'error'或2:违反时报错(退出码非 0,阻止 CI 通过)。
带选项的规则使用数组形式:['error', { option: value }]。
核心规则举例:
| 规则 | 说明 | 推荐设置 |
|---|---|---|
no-unused-vars |
禁止未使用的变量。 | 'warn' |
no-console |
禁止使用 console(生产环境推荐 warn 或 error)。 |
'warn' |
no-debugger |
禁止 debugger 语句。 |
'error' |
eqeqeq |
要求使用 === 和 !==。 |
'error' |
curly |
要求所有控制语句使用大括号。 | 'error' |
prefer-const |
要求用 const 声明不再赋值的变量。 |
'error' |
no-var |
要求使用 let 或 const 代替 var。 |
'error' |
no-multiple-empty-lines |
禁止多个连续空行。 | ['error', { max: 1 }] |
max-len |
限制行最大长度。 | ['warn', { code: 120 }] |
2.4 extends:继承共享配置
extends 可以引入一系列预定义的规则集合,避免从零配置。
eslint:recommended:ESLint 内置的推荐规则集,包含no-undef、no-unused-vars等基本检查。这是必须包含的基础。- **
plugin:vue/vue3-recommended**:Vue 3 官方推荐规则。 - **
plugin:@typescript-eslint/recommended**:TypeScript 推荐规则。 - **
airbnb**(需安装eslint-config-airbnb):Airbnb 的严格风格指南。 - **
standard**(需安装eslint-config-standard):StandardJS 风格。 - **
prettier**(需安装eslint-config-prettier):关闭所有与 Prettier 冲突的规则。
extends 中的配置按从后到前的顺序叠加(后面覆盖前面)。
1 | extends: [ |
2.5 plugins:扩展 ESLint 的能力
插件提供了额外的规则集合,但本身不会启用任何规则——你需要在 rules 中手动启用,或通过 extends 引入插件自带的推荐配置。
常用插件:
@typescript-eslint/eslint-plugin:TypeScript 专用规则。eslint-plugin-vue:Vue 单文件组件规则。eslint-plugin-react:React 规则(JSX、Hooks 检查)。eslint-plugin-import:模块导入顺序和路径检查。eslint-plugin-prettier:将 Prettier 作为 ESLint 规则运行(可选,更推荐的方式见下文)。
3. ESLint 与 Prettier 的集成
3.1 分工边界
- ESLint:关注代码质量(潜在 Bug、错误用法)和部分风格(如
eqeqeq、no-var)。它的格式化能力有限且不专业。 - Prettier:关注纯粹的代码格式(缩进、引号、分号、行宽、尾随逗号)。它是“固执己见”的格式化器,选项极少,保证团队代码风格完全一致。
核心原则:让 ESLint 做逻辑检查,让 Prettier 做格式化。不要用 ESLint 的格式化规则与 Prettier 竞争。
3.2 解决规则冲突:eslint-config-prettier
eslint-config-prettier 是一个 ESLint 共享配置,它的唯一作用是关闭所有与 Prettier 冲突的 ESLint 规则。安装后,在 extends 数组的最后添加 'prettier'(仅一个单词):
1 | npm install -D eslint-config-prettier |
1 | extends: [ |
这样就无需手动逐条关闭规则。
3.3 不推荐 eslint-plugin-prettier 的原因
eslint-plugin-prettier 将 Prettier 作为 ESLint 规则运行,在 ESLint 输出中直接显示格式错误。它看起来方便,但实际上有缺点:
- 它增加了 ESLint 的运行负担。
- 保存自动格式化通常由编辑器插件直接完成(更快,体验更好)。
- 在 CI 中,直接运行
prettier --check更简洁。
现代最佳实践:分别运行 eslint 和 prettier,使用 eslint-config-prettier 禁用冲突规则,编辑器插件各自处理保存时的自动修复和格式化。
4. Prettier 配置
Prettier 的设计哲学是尽可能少的选项。它通过 .prettierrc 文件配置,或直接在 package.json 的 prettier 字段中配置。
1 | { |
常用选项详解:
| 选项 | 默认值 | 说明 | 推荐值 |
|---|---|---|---|
printWidth |
80 |
每行最大字符数。 | 120 |
tabWidth |
2 |
缩进宽度。 | 2 |
semi |
true |
是否在语句末尾添加分号。 | true |
singleQuote |
false |
使用单引号而非双引号。 | true |
trailingComma |
'es5' |
多行时尾随逗号:'none'、'es5'(ES5 支持的位置)、'all'(所有可能位置)。 |
'all' |
bracketSpacing |
true |
对象大括号内添加空格 { foo: bar }。 |
true |
arrowParens |
'always' |
箭头函数参数始终加括号。 | 'always' |
**.prettierignore**:排除不需要格式化的文件:
1 | dist/ |
5. 编辑器集成与自动修复
5.1 VS Code 插件
- ESLint:安装
dbaeumer.vscode-eslint插件。在.vscode/settings.json中配置保存自动修复:
1 | { |
- Prettier:安装
esbenp.prettier-vscode插件,并将其设为默认格式化器:
1 | { |
重要:确保 ESLint 和 Prettier 保存时不会冲突——ESLint 仅执行逻辑规则的自动修复(如 no-unused-vars 的删除未使用变量修复),格式化由 Prettier 负责。以上配置已通过 source.fixAll.eslint(仅修复可修复的 ESLint 规则)和 formatOnSave(Prettier 格式化)明确分工。
5.2 JetBrains IDEs(WebStorm 等)
WebStorm 内置了 ESLint 和 Prettier 集成,勾选“Run eslint –fix on save”和“Run Prettier on save”即可。
6. Husky 与 lint-staged:Git 提交前自动检查
仅在编辑器层面检查代码质量是不够的——团队成员可能未配置插件、或绕过检查直接提交代码。Git Hooks 可以在 git commit 之前自动执行 lint 和格式化,从流程上杜绝不符合规范的代码进入仓库。
6.1 Husky:管理 Git Hooks
Husky 是一个简化 Git Hooks 配置的工具。
安装与初始化(Husky v9+):
1 | npm install -D husky |
该命令会在 .husky/ 目录下生成一个 pre-commit 钩子文件。
6.2 lint-staged:仅对暂存文件执行检查
lint-staged 与 Husky 配合,在 pre-commit 时仅对已暂存(staged)的文件运行 linter 和格式化工具,而非整个项目。这能确保速度快且渐进式地改进代码质量。
安装:
1 | npm install -D lint-staged |
配置(在 package.json 中):
1 | { |
**修改 .husky/pre-commit**:
1 | npx lint-staged |
现在每当执行 git commit 时,Husky 触发 pre-commit 钩子,lint-staged 自动对所有暂存文件运行 ESLint 修复和 Prettier 格式化。如果有 ESLint 错误('error' 级别),提交会被阻止。
7. 综合实战:一个完整的 ESLint + Prettier + Husky 配置
安装所有依赖:
1 | npm install -D eslint prettier eslint-config-prettier husky lint-staged |
**.eslintrc.js**:
1 | module.exports = { |
**.prettierrc**:
1 | { |
**package.json**(相关片段):
1 | { |
课后练习
一、概念自测(选择题 / 填空题)
(单选) ESLint 的
extends配置中,'prettier'(eslint-config-prettier)的作用是什么?
A. 启用 Prettier 的所有格式化规则。
B. 将 Prettier 作为 ESLint 的一个规则运行。
C. 关闭所有与 Prettier 冲突的 ESLint 规则。
D. 为 ESLint 添加格式化功能。(单选)
lint-staged工具的主要目的是?
A. 在 CI 服务器上运行整个项目的 lint。
B. 仅在 Git 暂存区的文件上运行 lint 和格式化,加快提交前检查。
C. 替代 ESLint 和 Prettier。
D. 生成代码覆盖率报告。(填空) Prettier 配置文件中,要每行最大字符数设为 120,应设置
______选项。(多选) 以下哪些是 ESLint 和 Prettier 在现代前端项目中的正确分工?
A. ESLint 负责代码风格(缩进、引号、分号等)。
B. Prettier 负责代码格式化(缩进、引号、分号等)。
C. ESLint 负责代码质量检查(潜在错误、最佳实践)。
D. Prettier 负责检查未使用的变量。
二、AI 编程任务:编写面向 AI 的提示词
场景:你需要为一个 Vue 3 + TypeScript + Vite 项目配置完整的代码规范体系。要求如下:
- 安装并配置 ESLint,使用
eslint:recommended、plugin:vue/vue3-recommended、@typescript-eslint/recommended,并用eslint-config-prettier关闭冲突。 - 配置 Prettier(单引号、分号、尾随逗号 all、打印宽度 120)。
- 配置
lint-staged对暂存的.vue、.ts、.js文件执行eslint --fix和prettier --write,对其他文件仅执行prettier --write。 - 添加
package.json的 lint 和 format 脚本。 - 创建 Husky pre-commit 钩子,调用
npx lint-staged。
任务要求:请写出一段完整的中文提示词,发送给 AI,使其生成所有需要的配置文件(package.json 相关字段、.eslintrc.js、.prettierrc、.husky/pre-commit)。提示词中需明确指定共享配置的顺序和 Prettier 选项。
三、Agent 模式下的提示词示例
你是一个资深前端开发 Agent。请为一个 Vue 3 + TypeScript + Vite 项目创建代码规范体系。需要生成/修改以下文件:
package.json:添加devDependencies包含eslint,prettier,eslint-plugin-vue,@typescript-eslint/parser,@typescript-eslint/eslint-plugin,eslint-config-prettier,husky,lint-staged。scripts 添加"lint": "eslint . --ext .vue,.ts,.js --fix","format": "prettier --write ."。lint-staged字段配置为"*.{vue,ts,js}": ["eslint --fix", "prettier --write"],"*.{css,scss,md,json}": ["prettier --write"]。.eslintrc.js:root: true, env, parser:'@typescript-eslint/parser', extends:['eslint:recommended', 'plugin:vue/vue3-recommended', '@typescript-eslint/recommended', 'prettier'], rules 设置no-console: 'warn',vue/multi-word-component-names: 'off'。.prettierrc:printWidth: 120,tabWidth: 2,semi: true,singleQuote: true,trailingComma: 'all'。- 运行
npx husky init后修改.husky/pre-commit内容为npx lint-staged。- 在
README.md中简要说明代码检查流程和如何手动运行 lint/format。
所有文件注释清晰,确保配置可直接使用。完成后列出所有文件内容。
四、面试真题与参考答案
题目(腾讯前端面试题):
请解释 ESLint 和 Prettier 在前端工程化中的职责分工。如果团队决定同时使用两者,如何避免它们的规则冲突?
lint-staged+ Husky 的工作流是如何工作的,解决了什么问题?
参考答案:
ESLint 和 Prettier 的核心分工:ESLint 是代码质量检查工具,负责检测潜在错误(如未使用的变量、不安全的写法、逻辑问题)和部分代码风格规则;Prettier 是代码格式化工具,专注于统一的代码视觉风格(缩进、引号、分号、行宽、尾随逗号)。两者各司其职,共同保证代码的正确性和一致性。
避免规则冲突的方式是安装 eslint-config-prettier,并在 ESLint 配置的 extends 数组的最后添加 'prettier'。这个共享配置会关闭所有与 Prettier 冲突的 ESLint 格式化规则,让 ESLint 仅专注于代码质量,格式化完全交给 Prettier。
lint-staged + Husky 工作流:Husky 管理 Git Hooks,在 git commit 之前触发 .husky/pre-commit 钩子;该钩子执行 npx lint-staged,后者读取配置中对不同文件类型的命令,仅对 git add 暂存的文件运行 ESLint 修复和 Prettier 格式化。如果有 ESLint 的 error 级别规则被触发,进程退出码非零,提交被阻止。这套工作流解决了两个问题:一是防止不合规代码进入仓库(在源头拦截);二是性能优化——仅检查暂存文件而非整个项目,使检查速度保持在秒级,不打断开发者工作流。
课后练习答案
一、概念自测答案
C
- 解析:
eslint-config-prettier的唯一作用就是关闭所有与 Prettier 冲突的 ESLint 规则。A 是 Prettier 自己的工作;B 描述的是eslint-plugin-prettier;D 不准确。
- 解析:
B
- 解析:
lint-staged仅在暂存文件上运行检查,速度快,适合 pre-commit 钩子。A 是通常的npm run lint脚本;C、D 错误。
- 解析:
printWidth- 解析:Prettier 使用
printWidth控制行最大宽度。
- 解析:Prettier 使用
B、C
- 解析:A 错误,代码风格是 Prettier 的职责;B 正确;C 正确;D 错误,Prettier 不关心逻辑问题。
二、AI 编程任务参考答案(提示词示例)
示例提示词:
“请为一个 Vue 3 + TypeScript 项目创建 ESLint + Prettier + Husky + lint-staged 配置。要求:
package.json添加所需 devDependencies、scripts(lint,format)和lint-staged配置。.eslintrc.js使用eslint:recommended、plugin:vue/vue3-recommended、@typescript-eslint/recommended和prettier(最后)。.prettierrc设置singleQuote: true,semi: true,trailingComma: 'all',printWidth: 120。.husky/pre-commit执行npx lint-staged。- 所有配置添加注释说明。直接输出所有文件内容。”