WinddSnow

Code-Linting-and-Formatting-ESLint-Prettier-Husky-lint-staged

字数统计: 4.3k阅读时长: 18 min
2026/07/31

第84课:代码规范:ESLint + Prettier——配置、规则、与编辑器集成、lint-staged + Husky

高质量的代码不仅在功能上正确,还应该在风格一致低错误风险可维护性上达到团队标准。手动审查代码风格既低效又不可靠,因此前端工程化体系引入了两类自动化工具:ESLint 负责代码质量检查与潜在错误发现(逻辑错误、未使用的变量、不安全写法),Prettier 负责代码格式化(缩进、引号、分号等风格统一)。两者分工明确,配合使用可以大幅减少 Code Review 中的风格争议,让团队专注于逻辑和架构。本节课将系统讲解 ESLint 的配置体系、规则集与共享配置、Prettier 的选项与最佳实践、两者集成时冲突的解决,以及通过 Huskylint-staged 在 Git 提交前自动执行检查的完整工作流。


1. ESLint 概述与核心价值

ESLint 是 JavaScript 生态中最主流的静态代码分析工具。它在不执行代码的情况下分析源码,根据可配置的规则集检测潜在问题——包括语法错误、最佳实践偏离、潜在 Bug 以及风格不一致。

ESLint 的核心特征:

  • 可完全配置:每条规则都可以设为 off/warn/error,并支持自定义参数。
  • 插件化架构:通过插件扩展对 TypeScript、Vue、React、JSX 等语法的支持。
  • 自动修复:很多规则支持 --fix,自动修复代码风格问题。
  • 共享配置:社区提供了大量预设规则集(eslint:recommendedairbnbstandard),开箱即用。

1.1 快速初始化

1
npm init @eslint/config

该向导会询问项目类型、框架、使用的模块系统、是否使用 TypeScript 等,并生成对应的 .eslintrc 配置文件。

1.2 配置文件格式

ESLint 支持多种配置文件格式(按优先级从高到低):.eslintrc.js.eslintrc.cjs.eslintrc.yaml.eslintrc.jsonpackage.json 中的 eslintConfig 字段。**推荐使用 .eslintrc.js**(或 .eslintrc.cjs),因为它支持注释和动态配置,灵活性最高。


2. ESLint 配置体系详解

一个典型的 ESLint 配置文件包含以下顶层字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// .eslintrc.js
module.exports = {
root: true, // 停止向上查找配置文件(在 monorepo 中重要)
env: {
browser: true, // 允许浏览器全局变量(window、document)
node: true, // 允许 Node.js 全局变量(process、require)
es2022: true, // 允许 ES2022 全局变量及语法
},
parserOptions: {
ecmaVersion: 'latest', // ECMAScript 版本
sourceType: 'module', // 'script'(默认)或 'module'(ESM)
ecmaFeatures: {
jsx: true // 启用 JSX 解析
}
},
extends: [
'eslint:recommended', // ESLint 内置推荐规则
// 其他共享配置
],
plugins: [], // 第三方插件
rules: { // 自定义规则覆盖
'no-unused-vars': 'warn',
'no-console': 'off',
'semi': ['error', 'always'],
'quotes': ['error', 'single'],
}
};

2.1 env:声明运行环境

env 告诉 ESLint 代码将在哪些环境中运行,从而允许使用对应环境的全局变量而不会触发 no-undef 规则。

环境变量 允许的全局对象
browser windowdocumentlocalStorage
node processrequiremodule__dirname
es2022 允许 ES2022 语法及全局变量
jest describeitexpect 等测试全局变量
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
2
3
4
5
6
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json', // TypeScript 项目配置,用于类型感知规则
},
};

2.3 rules:规则配置

每条规则的值可以是:

  • 'off'0:关闭规则。
  • 'warn'1:违反时发出警告(不阻止 CI)。
  • 'error'2:违反时报错(退出码非 0,阻止 CI 通过)。

带选项的规则使用数组形式:['error', { option: value }]

核心规则举例

规则 说明 推荐设置
no-unused-vars 禁止未使用的变量。 'warn'
no-console 禁止使用 console(生产环境推荐 warnerror)。 'warn'
no-debugger 禁止 debugger 语句。 'error'
eqeqeq 要求使用 ===!== 'error'
curly 要求所有控制语句使用大括号。 'error'
prefer-const 要求用 const 声明不再赋值的变量。 'error'
no-var 要求使用 letconst 代替 var 'error'
no-multiple-empty-lines 禁止多个连续空行。 ['error', { max: 1 }]
max-len 限制行最大长度。 ['warn', { code: 120 }]

2.4 extends:继承共享配置

extends 可以引入一系列预定义的规则集合,避免从零配置。

  • eslint:recommended:ESLint 内置的推荐规则集,包含 no-undefno-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
2
3
4
5
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier', // 必须放在最后,以覆盖所有冲突的规则
],

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、错误用法)和部分风格(如 eqeqeqno-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
2
3
4
5
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier', // 关闭冲突规则,确保放在最后
],

这样就无需手动逐条关闭规则。

3.3 不推荐 eslint-plugin-prettier 的原因

eslint-plugin-prettier 将 Prettier 作为 ESLint 规则运行,在 ESLint 输出中直接显示格式错误。它看起来方便,但实际上有缺点:

  • 它增加了 ESLint 的运行负担。
  • 保存自动格式化通常由编辑器插件直接完成(更快,体验更好)。
  • 在 CI 中,直接运行 prettier --check 更简洁。

现代最佳实践:分别运行 eslintprettier,使用 eslint-config-prettier 禁用冲突规则,编辑器插件各自处理保存时的自动修复和格式化。


4. Prettier 配置

Prettier 的设计哲学是尽可能少的选项。它通过 .prettierrc 文件配置,或直接在 package.jsonprettier 字段中配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"jsxSingleQuote": false,
"trailingComma": "all",
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "always",
"endOfLine": "lf"
}

常用选项详解

选项 默认值 说明 推荐值
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
2
3
4
5
dist/
node_modules/
coverage/
*.min.js
pnpm-lock.yaml

5. 编辑器集成与自动修复

5.1 VS Code 插件

  • ESLint:安装 dbaeumer.vscode-eslint 插件。在 .vscode/settings.json 中配置保存自动修复:
1
2
3
4
5
6
7
8
9
10
11
12
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue"
]
}
  • Prettier:安装 esbenp.prettier-vscode 插件,并将其设为默认格式化器:
1
2
3
4
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
}

重要:确保 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
2
npm install -D husky
npx husky init

该命令会在 .husky/ 目录下生成一个 pre-commit 钩子文件。

6.2 lint-staged:仅对暂存文件执行检查

lint-staged 与 Husky 配合,在 pre-commit 时仅对已暂存(staged)的文件运行 linter 和格式化工具,而非整个项目。这能确保速度快且渐进式地改进代码质量。

安装

1
npm install -D lint-staged

配置(在 package.json 中):

1
2
3
4
5
6
7
8
9
10
11
{
"lint-staged": {
"*.{js,jsx,ts,tsx,vue}": [
"eslint --fix",
"prettier --write"
],
"*.{css,scss,less,md,json}": [
"prettier --write"
]
}
}

**修改 .husky/pre-commit**:

1
npx lint-staged

现在每当执行 git commit 时,Husky 触发 pre-commit 钩子,lint-staged 自动对所有暂存文件运行 ESLint 修复和 Prettier 格式化。如果有 ESLint 错误('error' 级别),提交会被阻止。


7. 综合实战:一个完整的 ESLint + Prettier + Husky 配置

安装所有依赖

1
2
3
npm install -D eslint prettier eslint-config-prettier husky lint-staged
# TypeScript 项目需额外安装
npm install -D @typescript-eslint/parser @typescript-eslint/eslint-plugin

**.eslintrc.js**:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
root: true,
env: { browser: true, node: true, es2022: true },
parser: '@typescript-eslint/parser',
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier', // 必须在最后
],
rules: {
'no-console': 'warn',
'eqeqeq': 'error',
'prefer-const': 'error',
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
},
};

**.prettierrc**:

1
2
3
4
5
6
7
{
"printWidth": 120,
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"trailingComma": "all"
}

**package.json**(相关片段):

1
2
3
4
5
6
7
8
9
10
11
12
{
"scripts": {
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.vue",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx,.vue --fix",
"format": "prettier --write .",
"format:check": "prettier --check ."
},
"lint-staged": {
"*.{js,jsx,ts,tsx,vue}": ["eslint --fix", "prettier --write"],
"*.{css,scss,md,json}": ["prettier --write"]
}
}

课后练习

一、概念自测(选择题 / 填空题)

  1. (单选) ESLint 的 extends 配置中,'prettier'eslint-config-prettier)的作用是什么?
    A. 启用 Prettier 的所有格式化规则。
    B. 将 Prettier 作为 ESLint 的一个规则运行。
    C. 关闭所有与 Prettier 冲突的 ESLint 规则。
    D. 为 ESLint 添加格式化功能。

  2. (单选) lint-staged 工具的主要目的是?
    A. 在 CI 服务器上运行整个项目的 lint。
    B. 仅在 Git 暂存区的文件上运行 lint 和格式化,加快提交前检查。
    C. 替代 ESLint 和 Prettier。
    D. 生成代码覆盖率报告。

  3. (填空) Prettier 配置文件中,要每行最大字符数设为 120,应设置 ______ 选项。

  4. (多选) 以下哪些是 ESLint 和 Prettier 在现代前端项目中的正确分工?
    A. ESLint 负责代码风格(缩进、引号、分号等)。
    B. Prettier 负责代码格式化(缩进、引号、分号等)。
    C. ESLint 负责代码质量检查(潜在错误、最佳实践)。
    D. Prettier 负责检查未使用的变量。

二、AI 编程任务:编写面向 AI 的提示词

场景:你需要为一个 Vue 3 + TypeScript + Vite 项目配置完整的代码规范体系。要求如下:

  • 安装并配置 ESLint,使用 eslint:recommendedplugin:vue/vue3-recommended@typescript-eslint/recommended,并用 eslint-config-prettier 关闭冲突。
  • 配置 Prettier(单引号、分号、尾随逗号 all、打印宽度 120)。
  • 配置 lint-staged 对暂存的 .vue.ts.js 文件执行 eslint --fixprettier --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 项目创建代码规范体系。需要生成/修改以下文件:

  1. 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"]
  2. .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'
  3. .prettierrcprintWidth: 120, tabWidth: 2, semi: true, singleQuote: true, trailingComma: 'all'
  4. 运行 npx husky init 后修改 .husky/pre-commit 内容为 npx lint-staged
  5. 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 级别规则被触发,进程退出码非零,提交被阻止。这套工作流解决了两个问题:一是防止不合规代码进入仓库(在源头拦截);二是性能优化——仅检查暂存文件而非整个项目,使检查速度保持在秒级,不打断开发者工作流。


课后练习答案

一、概念自测答案

  1. C

    • 解析:eslint-config-prettier 的唯一作用就是关闭所有与 Prettier 冲突的 ESLint 规则。A 是 Prettier 自己的工作;B 描述的是 eslint-plugin-prettier;D 不准确。
  2. B

    • 解析:lint-staged 仅在暂存文件上运行检查,速度快,适合 pre-commit 钩子。A 是通常的 npm run lint 脚本;C、D 错误。
  3. printWidth

    • 解析:Prettier 使用 printWidth 控制行最大宽度。
  4. 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:recommendedplugin:vue/vue3-recommended@typescript-eslint/recommendedprettier(最后)。
  • .prettierrc 设置 singleQuote: true, semi: true, trailingComma: 'all', printWidth: 120
  • .husky/pre-commit 执行 npx lint-staged
  • 所有配置添加注释说明。直接输出所有文件内容。”
CATALOG
  1. 1. 第84课:代码规范:ESLint + Prettier——配置、规则、与编辑器集成、lint-staged + Husky
    1. 1.1. 1. ESLint 概述与核心价值
      1. 1.1.1. 1.1 快速初始化
      2. 1.1.2. 1.2 配置文件格式
    2. 1.2. 2. ESLint 配置体系详解
      1. 1.2.1. 2.1 env:声明运行环境
      2. 1.2.2. 2.2 parserOptions:解析器选项
      3. 1.2.3. 2.3 rules:规则配置
      4. 1.2.4. 2.4 extends:继承共享配置
      5. 1.2.5. 2.5 plugins:扩展 ESLint 的能力
    3. 1.3. 3. ESLint 与 Prettier 的集成
      1. 1.3.1. 3.1 分工边界
      2. 1.3.2. 3.2 解决规则冲突:eslint-config-prettier
      3. 1.3.3. 3.3 不推荐 eslint-plugin-prettier 的原因
    4. 1.4. 4. Prettier 配置
    5. 1.5. 5. 编辑器集成与自动修复
      1. 1.5.1. 5.1 VS Code 插件
      2. 1.5.2. 5.2 JetBrains IDEs(WebStorm 等)
    6. 1.6. 6. Husky 与 lint-staged:Git 提交前自动检查
      1. 1.6.1. 6.1 Husky:管理 Git Hooks
      2. 1.6.2. 6.2 lint-staged:仅对暂存文件执行检查
    7. 1.7. 7. 综合实战:一个完整的 ESLint + Prettier + Husky 配置
    8. 1.8. 课后练习
      1. 1.8.1. 一、概念自测(选择题 / 填空题)
      2. 1.8.2. 二、AI 编程任务:编写面向 AI 的提示词
      3. 1.8.3. 三、Agent 模式下的提示词示例
      4. 1.8.4. 四、面试真题与参考答案
    9. 1.9. 课后练习答案
      1. 1.9.1. 一、概念自测答案
      2. 1.9.2. 二、AI 编程任务参考答案(提示词示例)