技术深度剖析
Prettier 的核心创新在于其 AST 重写流水线,这与基于正则表达式或文本的格式化工具有着根本区别。该流水线包含三个阶段:
1. 解析:使用特定语言的解析器将源代码解析为 AST。对于 JavaScript/TypeScript,Prettier 使用 Babel(通过 `@babel/parser`)和 TypeScript 编译器 API。对于 CSS,它使用 CSSTree。解析器生成一个由代表语法元素的节点(例如 `VariableDeclaration`、`FunctionExpression`)组成的树。
2. IR 生成:AST 被转换为称为 Doc 的中间表示(IR)——一个由格式化原语(如 `group`、`line`、`softline` 和 `indent`)组成的树。Doc 捕获了代码的逻辑结构,而不承诺特定的换行位置。
3. Doc 打印:使用一种 贪婪行宽算法 将 Doc 扁平化为字符串。该算法尝试在一行中容纳尽可能多的组,仅当行超过配置的打印宽度(默认 80)时才进行换行。这是 Wadler 的漂亮打印机所使用的优化适配算法的简化版本,以速度换取最优性。
关键技术权衡:
- 确定性:Prettier 保证相同的输入始终产生相同的输出,无论环境如何。这是通过忽略所有原始空白和注释(注释会重新附加到 AST 节点,但不会格式化)来实现的。
- 有限的可配置性:Prettier 仅提供约 20 个选项(例如 `tabWidth`、`singleQuote`、`trailingComma`)。这是有意为之:每个选项都会增加风格争论的余地,而 Prettier 旨在消除这些争论。
- 性能:Prettier 比基于正则表达式的格式化工具(例如 `js-beautify`)慢,因为它必须解析整个 AST。对于一个 10,000 行的文件,在现代硬件上 Prettier 大约需要 200 毫秒,而 `js-beautify` 大约需要 50 毫秒。然而,对于大多数项目来说,这种差异可以忽略不计。
相关的 GitHub 仓库:
- prettier/prettier(51,835 星):核心格式化工具。最近的更新包括改进的 TypeScript 5.0 支持和用于增量格式化的实验性 `--cache` 标志。
- prettier/plugin-ruby(1,200 星):用于 Ruby 格式化的社区插件,展示了插件架构的可扩展性。
- trivago/prettier-plugin-sort-imports(3,500 星):用于排序导入语句的热门插件,现已集成到 Prettier 的官方生态系统中。
基准测试数据:
| 格式化工具 | 语言 | 每 1K 行平均耗时 | 确定性? | 配置选项 |
|---|---|---|---|---|
| Prettier 3.4 | JS/TS | 20ms | 是 | ~20 |
| ESLint --fix | JS/TS | 35ms | 否(依赖规则) | 数百 |
| dprint(基于 Rust) | JS/TS | 5ms | 是 | ~15 |
| clang-format | C++ | 8ms | 是 | ~100 |
数据要点:Prettier 处于性能谱系的中游,以原始速度换取广泛的语言支持和生态系统集成。其确定性输出是其杀手锏,但像 dprint 这样基于 Rust 的替代方案正在对速度敏感的 CI 流水线中崭露头角。
关键参与者与案例研究
James Long(原作者)和 Christopher Chedeau(现任首席维护者)塑造了 Prettier 的理念:“结束风格争论的唯一方法是消除配置风格的能力。”这一立场在主要公司的采用中得到了验证:
- Airbnb:在经历了多年的 ESLint 配置之争后,于 2018 年采用了 Prettier。他们的内部研究表明,在代码审查中用于格式化评论的时间减少了 40%。
- Vercel:在所有前端仓库中使用 Prettier,并与 `lint-staged` 集成,以便在预提交钩子中仅格式化已更改的文件。
- Meta (React):Prettier 是 React 核心和 React Native 仓库的默认格式化工具,取代了自定义的格式化脚本。
竞争解决方案:
| 工具 | 方法 | 优势 | 劣势 |
|---|---|---|---|
| Prettier | AST 重写 | 确定性、广泛的语言支持、庞大的生态系统 | 大文件速度慢、可配置性有限 |
| dprint | 基于 Rust 的 AST 重写 | 比 Prettier 快 10 倍,支持 JS/TS/JSON/Markdown | 插件生态系统较小,社区采用度较低 |
| ESLint Stylistic | 基于规则的格式化 | 高度可配置,与 linting 集成 | 非确定性、规则冲突、速度较慢 |
| Biome (Rome) | 基于 Rust 的一体化工具 | 快速,结合了 linter 和格式化工具 | 仍处于测试阶段,语言插件较少 |
数据要点:Prettier 的生态系统优势(VS Code 扩展安装量超过 5000 万,npm 上有 1200 多个插件包)创造了竞争对手难以打破的网络效应。然而,dprint 和 Biome 正通过提供 10 倍的性能提升来缩小差距,这对于拥有超过 10 万个文件的 monorepo 来说至关重要。
行业影响与市场动态
Prettier 从根本上重塑了开发者工具格局:
- ESLint 的转向:2023 年,ESLint 弃用了所有格式化规则(例如 `indent`、`quotes`),转而支持 Prettier。这是一个明确的 ad