ESLint + Prettier + Husky + lint-staged:建立自动化的高效前端工作流
作者:互联网
2026-03-22
前言
在团队协作中,代码规范往往是一个容易引发争议却又不得不解决的问题。每个人都有自己的编码习惯,有人喜欢加分号,有人不喜欢;有人用两个空格缩进,有人用四个;有人变量命名用 camelCase,有人用 snake_case。这些差异在 Code Review 时往往演变成无休止的争论,消耗着团队的宝贵时间。
这就是为什么要建立自动化代码规范工作流——让工具做工具擅长的事,让人做人擅长的事。
为什么需要自动化代码规范?
没有规范带来的问题
// 团队成员A写的代码
function fetchData(){
let result = getData()
return result
}
// 团队成员B写的代码
function fetchData() {
const result = getData();
return result;
}
上述两段代码看起来差不多,但:
- 格式不一致(缩进、空格、分号)
- 变量命名风格不同
- Code Review 时会争论这些细节
有了自动化工具之后
// 不管我们怎么写,保存时自动变成统一格式
function fetchData() {
const result = getData()
return result
}
// 提交时自动检查,有问题就拦截
// 再也不用手动改格式了
自动化工作流的价值
传统流程:
写代码 → 手动检查 → 提交 → Code Review → 发现问题 → 修改 → 再次提交
自动化流程:
写代码 → 保存时自动格式化 → 提交时自动检查 → 提交成功
↓
发现问题自动拦截
收益:
- 减少 90% 的代码风格争论
- 提前发现 70% 的潜在错误
- Code Review 时间缩短 50%
- 新人融入时间减少 60%
工具链全景图
四大工具的分工
ESLint:代码质量检查
- 发现潜在错误(未定义变量、未使用变量)
- 强制最佳实践(使用 === 代替 ==)
- 统一代码风格(但能力有限)
Prettier:代码美容师
- 统一代码风格(空格、换行、引号)
- 专注格式化,不做质量检查
Husky:看门人
- 在 Git 操作时触发脚本
- 确保提交前代码符合规范
lint-staged:高效助手
- 只检查即将提交的文件
- 避免检查整个项目,提高效率
工作流程示意图
开发阶段
┌─────────────────┐
│ VS Code 编辑器 │
│ - 保存时格式化 │
│ - 实时错误提示 │
└────────┬────────┘
↓
Git 提交阶段
┌─────────────────┐
│ git commit │
└────────┬────────┘
↓
Husky 触发 pre-commit
┌─────────────────┐
│ 执行 lint-staged│
└────────┬────────┘
↓
lint-staged 检查暂存区
┌─────────────────┐
│ 1. 运行 ESLint │
│ 2. 运行 Prettier│
└────────┬────────┘
有问题?→ 拦截提交
↓
没问题 → 提交成功
ESLint - 代码质量守门员
什么是 ESLint?
ESLint 就像考试时的阅卷老师,专门帮我们找出代码中的"错误"和"不规范":
// 1. 未使用的变量
let unusedVar = '没人用我' // ESLint: 'unusedVar' is defined but never used
// 2. 未定义的变量
console.log(notDefined) // ESLint: 'notDefined' is not defined
// 3. 不安全的比较
if (count == 1) { // ESLint: Expected '===' and instead saw '=='
// ...
}
// 4. 重复定义
let name = '张三'
let name = '李四' // ESLint: 'name' is already defined
安装和初始化
# 安装 ESLint
npm install eslint --save-dev
# 初始化配置
npx eslint --init
# 交互式选择:
# - How would you like to use ESLint? → To check syntax and find problems
# - What type of modules does your project use? → JavaScript modules (import/export)
# - Which framework does your project use? → Vue.js
# - Does your project use TypeScript? → Yes
# - Where does your code run? → Browser
# - What format do you want your config file to be in? → JavaScript
Vue 3 + TypeScript 项目的最佳配置
// .eslintrc.js
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true,
'vue/setup-compiler-macros': true
},
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended', // 使用推荐规则
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended' // 整合 Prettier
],
parser: 'vue-eslint-parser',
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module',
extraFileExtensions: ['.vue']
},
plugins: ['vue', '@typescript-eslint'],
rules: {
// 关闭与 Prettier 冲突的规则
'vue/max-attributes-per-line': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/html-self-closing': 'off',
// 自定义规则
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// Vue 3 推荐
'vue/multi-word-component-names': 'off',
'vue/no-v-model-argument': 'off',
// TypeScript
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_'
}]
},
globals: {
defineProps: 'readonly',
defineEmits: 'readonly',
defineExpose: 'readonly',
withDefaults: 'readonly'
}
}
自定义规则详解
// .eslintrc.js
module.exports = {
rules: {
// 规则级别:off(0) 关闭 / warn(1) 警告 / error(2) 错误
// ========== 最佳实践 ==========
'eqeqeq': ['error', 'always'], // 必须用 === 和 !==
'no-eval': 'error', // 禁止 eval
'no-implied-eval': 'error', // 禁止隐式 eval
'no-with': 'error', // 禁止 with 语句
// ========== 变量相关 ==========
'no-unused-vars': ['error', {
vars: 'all', // 检查所有变量
args: 'after-used', // 检查使用后的参数
ignoreRestSiblings: true // 忽略剩余参数
}],
'no-use-before-define': ['error', {
functions: false, // 函数可以在定义前使用
classes: true, // 类不行
variables: true // 变量也不行
}],
// ========== 代码风格 ==========
// 这些规则会被 Prettier 覆盖,但保留作为参考
'array-bracket-spacing': ['error', 'never'], // [1, 2, 3] 而不是 [ 1, 2, 3 ]
'object-curly-spacing': ['error', 'always'], // { foo: bar } 而不是 {foo: bar}
'comma-dangle': ['error', 'never'], // 不加尾逗号
'quotes': ['error', 'single'], // 用单引号
'semi': ['error', 'never'], // 不加分号
// ========== 复杂度控制 ==========
'max-depth': ['warn', 4], // 最大嵌套深度不超过4
'max-params': ['warn', 5], // 函数参数不超过5个
'max-statements': ['warn', 30], // 函数语句不超过30行
'complexity': ['warn', 10] // 圈复杂度不超过10
}
}
在 package.json 中添加脚本
{
"scripts": {
"lint": "eslint . --ext .js,.ts,.vue",
"lint:fix": "eslint . --ext .js,.ts,.vue --fix",
"lint:src": "eslint src --ext .js,.ts,.vue"
}
}
Prettier - 代码美容师
什么是 Prettier?
Prettier 是格式化工具,它只有一个任务:把代码变得好看:
// 这是我们写的(乱七八糟)
function hello( name ){
console.log( `Hello ${ name }` ) }
// Prettier 帮我们变成这样
function hello(name) {
console.log(`Hello ${name}`)
}
安装与基础配置
# 安装 Prettier
npm install --save-dev prettier
# 安装 ESLint 整合插件
npm install --save-dev eslint-config-prettier eslint-plugin-prettier
Prettier 配置文件
// .prettierrc.js
module.exports = {
// 基础配置
printWidth: 100, // 每行最大宽度
tabWidth: 2, // 缩进空格数
useTabs: false, // 用空格代替 tab
semi: false, // 不加分号
singleQuote: true, // 用单引号
quoteProps: 'as-needed', // 对象属性只在必要时加引号
trailingComma: 'none', // 不加尾逗号
bracketSpacing: true, // 对象括号内加空格 { foo: bar }
arrowParens: 'always', // 箭头函数参数总是加括号 (x) => x
endOfLine: 'auto', // 自动处理换行符
// Vue 相关
vueIndentScriptAndStyle: true, // 缩进
