Pretext — 绕过 DOM 的文本布局引擎
一个纯 TypeScript 库,在不触碰 DOM 的情况下测量和排版多行文本。48 小时内拿到 13,000+ GitHub stars。 日期:2026-03-28 发布 作者:Cheng Lou(@chenglou) GitHub:https://github.com/chenglou/pretext
核心问题
每个前端开发者都遇到过这个场景:你需要知道一段文本在特定宽度下有多高。浏览器给你的唯一办法是把元素塞进 DOM,然后读 offsetHeight 或调 getBoundingClientRect()。
这会触发同步 reflow。一条消息无所谓,几千条消息呢?
聊天应用的虚拟滚动就是个典型的受害者。每个气泡要先量出高度才能定位,而高度只能从 DOM 拿。几千条消息,几千次 reflow,性能就崩了。
Pretext 怎么做
绕开 DOM,用数学算。
核心只有两个函数:
prepare()— 一次性完成文本分段、字素切割、Canvas 测量,返回缓存句柄。500 个文本块大约 19ms。layout()— 热路径,纯算术。同样 500 个块 0.09ms。
19ms 换一次,之后每次 0.09ms。你可以提前算出任何文本在任何宽度下的高度和行数,完全不需要碰浏览器布局引擎。
还有一个被低估的 API:walkLineRanges()。它做的是”多行 shrinkwrap”。CSS 的 width: fit-content 只能按最宽的折行定宽,最后一行短了就留大片空白。Pretext 用二分搜索找到”恰好 N 行”的最窄宽度,零 DOM 读取。做聊天气泡的人应该懂这意味着什么。
文本分段不是按空格切词
这部分是真正脏活累活:
- CJK 字符逐字断行
- 阿里语系标点聚类
- Emoji 宽度修正(Chrome 和 Firefox 在 macOS 上 Canvas 测量和 DOM 测量不一致)
- 双向文本(BiDi)
- 软连字符
早期版本把《了不起的盖茨比》全文跑过多个浏览器验证测量精度。这不是随便调个 API 就能搞定的事。
API 例子
只要高度:
const prepared = prepare('Hello 世界 🚀', '16px Inter')
const { height, lineCount } = layout(prepared, 320, 20)要每一行的内容:
const prepared = prepareWithSegments(text, '16px Inter')
const { lines } = layoutWithLines(prepared, 320, 20)layoutNextLine() 更有意思 — 每行可以设不同宽度。文字可以环绕图片流动,像杂志排版。
和 AI 编程有什么关系
Cheng Lou 设计 API 时说要 “AI-friendly”。这不是空话。
我之前在 Claude Code 源码分析里看到一个核心问题:AI agent 在编辑器里每改一行,工具调用 → 返回结果 → UI 更新,这个 loop 的流畅度直接决定编程体验。agent-driven 界面更极端 — UI 不是人提前设计的,是 AI 实时组装的,每次输出变化都触发布局更新。
现在大多数 agent UI 的卡顿来自网络延迟和 LLM token 流,不是浏览器布局。但对那些实时生成复杂界面的 agent 工具来说,布局计算的可预测性会成为真正的瓶颈。
具体到”编辑器与测试 loop”:AI 写代码 → 跑测试 → 展示结果 → 改代码。如果结果展示区要频繁重排大量文本(测试输出、diff 视图、日志流),每次都走 DOM reflow 就是在给已经够慢的 loop 加不必要的延迟。Pretext 让这部分几乎免费。
另一个容易被忽略的角度:开发时验证。AI 写的代码里按钮文字会不会溢出到第二行?以前靠人肉看或 DOM 测量,现在可以用 Pretext 在没有浏览器的环境里验证。CI/CD 和自动化测试里直接用。
局限
- 只能在浏览器跑,服务端渲染还没做
system-ui字体在 macOS 上 Canvas 和 DOM 解析出不同光学变体,得用命名字体- 非常窄的容器里断词位置可能出人意料
- 库才发布几天,生产环境要谨慎
争议
Domenic Denicola(Web 标准贡献者)批评说这只是 Canvas measureText() 的包装。
技术上没错,底层确实是 Canvas API。但把”正确匹配三大浏览器换行行为 + 处理所有国际化边界情况”叫做”包装”,就像把 React 叫做 document.createElement() 的包装。
真正有意思的问题在别处:CSS Exclusions 和 CSS Regions 规范写了多年,浏览器厂商就是不实现。Pretext 填的恰恰是这个空白 — 规范存在,实现不存在。如果 Pretext 够成功,反而可能降低浏览器厂商实现这些规范的动力。一种奇怪的”成功”。
我的判断
大多数网站不需要这东西。博客、落地页、电商站,CSS 完全够用。
值得关注的是这些场景:
- 聊天应用 — 虚拟滚动 + 气泡精确宽度
- Agent 驱动的 UI — AI 实时生成复杂界面时的布局性能
- 编辑器/IDE — 代码 diff、测试输出、日志流的频繁重排
- CI 测试 — 无浏览器环境验证文本布局
Cheng Lou 之前做过 Reason/ReScript,对开发者工具的品味一直不错。48 小时 13k stars 不是偶然 — 它解决了一个真实存在但大家习惯了忍受的痛点。布局计算从 DOM reflow 降到纯算术,是在不该有等待的地方省下了等待。
参考:
- GitHub: https://github.com/chenglou/pretext
- aiHola 分析: https://aihola.com/article/pretext-dom-free-text-layout
- Simon Willison 评价: https://simonwillison.net/2026/Mar/29/pretext/
- Claude Code 源码分析: https://yage.ai/share/claude-code-engineering-cost-20260331.html