JavaScript 工程化规范落地实战:从 Prettier/ESLint 到 pre-commit 的完整防线
为什么规范需要「落地」而不仅仅是「写一份文档」
团队规范最常见的两种结局:① 写在 Wiki 里无人问津;② 写在 Wiki 里每个人都用「我有自己的习惯」为由无视。
规范只有自动化、强制化,才叫落地。本文聚焦三类自动化:
- 格式 — Prettier 统一,零争议
- 质量 — ESLint 拦截,提前发现 Bug
- 门禁 — pre-commit 强制执行,不让坏代码进仓库
1. ESLint + Prettier:分工明确,互不打架
反例:配置冲突
// .eslintrc.json — 新手常犯:格式化规则和逻辑规则混在一起
{
"rules": {
"indent": ["error", 2],
"quotes": ["error", "single"],
"no-var": "error"
}
}
这样配导致两个问题:
indent/quotes这类格式规则会和 Prettier 冲突- CI 里 ESLint 报格式错,本地 Prettier 却认为没问题,修复 A 引入 B 的飘红
正例:职责分离
npm i -D eslint prettier eslint-config-prettier eslint-plugin-prettier
// .eslintrc.cjs — 让 Prettier 管格式,ESLint 只管逻辑质量
module.exports = {
extends: [
'eslint:recommended',
'plugin:prettier/recommended' // 必须放最后,关闭 ESLint 的格式规则
],
rules: {
'no-var': 'error', // 不用 var
'prefer-const': 'error', // 能 const 不用 let
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'no-console': 'warn', // prod 前必须清
'require-await': 'error' // 无 await 的 async 大概率是 bug
}
}
// .prettierrc — 格式决策全部放在这里
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2
}
关键决策点:
eslint-config-prettier关闭 ESLint 中与 Prettier 冲突的所有规则plugin:prettier/recommended=extends: ['prettier']+plugins: ['prettier']+rules: { 'prettier/prettier': 'error' }三合一- 这样 Prettier 的违规会作为 ESLint 错误暴露,一条
eslint --fix搞定全部
2. 规则分层:error vs warn 的工程化决策
// .eslintrc.cjs rules 区段 — 有意识的分层
rules: {
// ── Layer 0: 立即阻塞提交的硬错误 ──
'no-var': 'error',
'no-const-assign': 'error',
'no-duplicate-imports': 'error',
'no-unreachable': 'error',
// ── Layer 1: 开发期警告,CI 里提级为 error ──
'no-console': 'warn',
'no-debugger': 'warn',
// ── Layer 2: 渐进迁移期的临时降级 ──
'@typescript-eslint/no-explicit-any': 'warn', // 先 warn,存量清理后升 error
}
为什么不在本地全开 error?
warn级别的no-console允许开发时打 log,但不让过 CI- 存量项目引入新规范时,先
warn再逐步升error,避免一次性改动爆炸
CI 中的覆盖策略:
# .github/workflows/lint.yml
- run: npx eslint . --max-warnings 0
--max-warnings 0 把 warn 也视为失败,保证 CI 零容忍。
3. pre-commit 防线:husky + lint-staged 精确打击
反例:在 pre-commit 里全量 lint
// package.json — 不推荐的做法
{
"husky": {
"hooks": {
"pre-commit": "npx eslint . && npx prettier --check ."
}
}
}
这导致改一个文件,全项目扫描十几秒以上,严重影响提交流畅度。
正例:lint-staged 只 check 暂存文件
npm i -D husky lint-staged
npx husky init
# .husky/pre-commit — Husky v9 写法
npx lint-staged
// package.json
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix --max-warnings 0",
"prettier --write"
],
"*.{json,md,yaml,css}": [
"prettier --write"
]
}
}
三条铁律:
- 只 lint staged 文件 — 改了 3 个文件就只看 3 个,耗时 < 1s
- 先 fix 再 check —
eslint --fix先自动修,修复失败才阻塞 - 按文件类型分离 —
.json不该跑 ESLint,.ts必须跑
4. 团队统一:Override Report 与 .vscode 共享
规范在编辑器里实时生效比 pre-commit 更重要——不要让开发者等到提交才看到飘红。
// .vscode/settings.json — 提交到仓库,全团队共享
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"]
}
// .vscode/extensions.json — 强制推荐插件
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
新人 clone 项目后 VSCode 会自动提示安装推荐的插件和 settings,零配置即可获得同样的保存自动修复体验。
5. 进阶:用 eslint-plugin-import 管 import 顺序
// .eslintrc.cjs 补充
{
plugins: ['import'],
rules: {
'import/order': ['error', {
groups: [
'builtin', // node:fs、node:path
'external', // react、lodash
'internal', // @/ 别名
['parent', 'sibling', 'index']
],
'newlines-between': 'always',
alphabetize: { order: 'asc', caseInsensitive: true }
}],
'import/no-cycle': 'error',
'import/no-self-import': 'error'
}
}
效果:
// ❌ 混乱的 import — 谁都会改着改着就乱了
import { debounce } from 'lodash';
import { Button } from '@/components/Button';
import fs from 'node:fs';
import React from 'react';
// ✅ 自动排序后
import fs from 'node:fs';
import { debounce } from 'lodash';
import React from 'react';
import { Button } from '@/components/Button';
配合 eslint --fix,import 排序全自动,review 不再为顺序浪费时间。
6. 完整落地 Checklist
| 阶段 | 做了什么 | 时间成本 |
|---|---|---|
| 初始化 | ESLint + Prettier + eslint-config-prettier | 10 min |
| 规则分层 | 区分 error / warn,CI 用 --max-warnings 0 | 5 min |
| pre-commit | husky + lint-staged,只处理 staged 文件 | 5 min |
| 编辑器 | .vscode/settings.json 共享,formatOnSave | 3 min |
| import 管理 | eslint-plugin-import 排序 + 循环检测 | 3 min |
| CI 强制 | GitHub Actions 跑 lint --max-warnings 0 | 5 min |
总计约 30 分钟,一劳永逸。
总结:规范落地的本质
- Prettier 管格式,ESLint 管质量 — 职责分离是避免冲突的第一原则
- warn 是过渡,error 是目标 — 用 --max-warnings 0 在 CI 中统一提级
- lint-staged 是效率关键 — 只查变更文件,让规范不成为开发的阻碍
- 编辑器配置进仓库 — 让规范在敲代码时就生效,而非提交时阻击
- CI 是最后一道防线 — 本地提交可能跳过 hook,但 CI 绕不过
规范不会让代码变好,但会让代码变好的可能性更高。
0 评论
评论区
登录 后参与评论