“代码格式化了还报 bug?“——Prettier 不是万能的。它只调整字符间距,不懂你代码在做什么。下面 7 类问题格式化工具救不了,得靠别的手段。
Prettier 能解决的
先说能的,对比着看才清楚边界:
- 引号:
'abc'↔"abc" - 缩进:tab 和空格、2 空格和 4 空格
- 分号:JS 语句末尾加不加
- 尾逗号:数组 / 对象 / 函数参数
- 换行:行超长自动折行
- 空格:
if(x)→if (x)、a:1→a: 1 - 对齐:多行对象键值对齐
- 属性顺序(部分语言)
所有这些都是纯排版问题,不涉及语义。
1. 重复的 object key
const config = {
port: 3000,
host: 'localhost',
port: 4000, ← 重名,后面覆盖前面
};
Prettier 按原样输出,因为语法合法。ESLint 规则 no-dupe-keys 会报错。
JSON 更危险——很多 parser 默认后者覆盖前者,但部分 schema validator 把它当错误。手写配置文件时最容易踩。
2. 未使用的变量 / import
import { foo, bar } from './lib'; ← bar 从没用
function calc(x, y) { ← y 从没用
return x * 2;
}
Prettier 原样留着。ESLint 的 no-unused-vars 和 TypeScript 的 noUnusedLocals 管这个。IDE 里通常显示灰色。
注意:下划线开头的变量名 (_unused) 按惯例表示”故意不用”,不同 lint 规则对它的处理不同。
3. 语义重复的条件
if (x > 0 && x > 0) { ... } ← 条件重复
if (a === b || a === b) { ... } ← 条件重复
if (x) { ... } else if (x) { ... } ← else if 永不触发
Prettier 老老实实输出。ESLint 的 no-dupe-else-if、no-dupe-boolean-conditions 能抓出来。
4. 永远触发 / 永不触发
if (true) { ... } ← 永真
if (false) { ... } ← 永假,dead code
while (1) break; ← 结构没错但意图可疑
const x = 5;
if (x < 0) { ... } ← const 已知为正数
Prettier 原样输出,TypeScript 的 narrowing 能识别部分,ESLint 的 no-constant-condition 能抓字面量。
5. JSX 属性顺序 / 重复
<input
type="text"
value={v}
type="email" ← 重复
onClick={f}
onClick={g} ← 重复
/>
Prettier 不报错——JSX 规范允许重复属性(后者覆盖前者)。ESLint 的 react/jsx-no-duplicate-props 必备。
6. CSS 变量 / 选择器错误
:root {
--brand: #336699;
}
.btn {
color: var(--brandd); ← 变量名拼错,无默认值=无效
background: #gggggg; ← 非法颜色值
padding: 10; ← 缺单位(合法但通常是 bug)
}
Prettier 只管缩进和空格,拼写错误完全不管。Stylelint 的 declaration-property-value-allowed-list、color-no-invalid-hex 能查。
padding: 10 在 SVG 或某些 CSS 属性里合法(无单位数字),在普通布局里往往是 bug。
7. TypeScript 类型问题
const age: string = 30; ← 类型不匹配
function greet(name: string) {
return `Hello ${nane}`; ← 拼错变量名
}
interface User {
id: number;
id: string; ← 接口重复字段
}
Prettier 完全无视——它在排版层,不做类型检查。这是 tsc --noEmit / astro check 的职责。
工具链分工
大项目的典型配置:
| 工具 | 职责 | 触发时机 |
|---|---|---|
| Prettier | 排版 | 保存时自动 / pre-commit |
| ESLint | JS / TS 质量 | pre-commit / CI |
| Stylelint | CSS 质量 | pre-commit / CI |
| TypeScript | 类型检查 | IDE 实时 / CI |
| Biome / oxc | 一体化(替代) | 新项目可选 |
| husky + lint-staged | 触发器 | git commit 时 |
冲突处理:Prettier 和 ESLint 在”引号 / 分号 / 缩进”上会打架。装 eslint-config-prettier,它会关掉 ESLint 里所有与 Prettier 冲突的规则,避免来回格式化。
一次 lint 搭建顺序
- 先装 Prettier:统一排版,消除”好看不好看”的争吵
- 再装 ESLint:抓 bug,别管排版
- 配
eslint-config-prettier:两者和平共处 - 装 husky + lint-staged:commit 前自动跑,坏代码进不了仓库
- CI 加
prettier --check和eslint:PR 必须过
顺序反过来(先 ESLint 后 Prettier)会长期打架。
压缩模式:何时用
Prettier 的”压缩/压扁”本质是去空白,不是混淆。生产环境真正的 minify 要用:
- JS/TS:esbuild / terser / swc
- CSS:cssnano / lightningcss
- HTML:html-minifier-terser
Prettier 的”压缩”只是开发过程中偶尔”一行化”用的,别当生产工具。
本地跑一下
粘入任意 JS/TS/JSON/CSS/HTML/Vue/MD/YAML/SQL/XML,一键格式化或压缩,多文件批量 ZIP 导出。本地运行不上传——公司代码、私有 schema 都能安全处理。