编程 pretext 开源:不碰 DOM 的文本测量引擎,比传统布局回流快 500 倍

2026-09-12 09:50:24

pretext 开源:不碰 DOM 的文本测量引擎,比传统布局回流快 500 倍

这两天在前端圈炸开锅的一个项目,短短几天就获得了海量关注。
仅三天,GitHub 标星直接狂飙到20.8K,目前还在持续上涨中。

该项目叫做pretext,很多开发者看完后拍案叫绝,直呼**「这才是我们真正需要的东西」**。
做前端的都知道,文本测量一直是个老大难问题。
要知道一段文字会占多大空间,传统做法必须先把它渲染到DOM里,然后用getBoundingClientRect或者offsetHeight去量。
这听起来简单,但每次测量都会触发浏览器的布局回流(reflow),这可是浏览器里最昂贵的操作之一。
每次性能优化,我们都在和这些DOM测量做斗争。几万条消息量下来,页面直接卡死。
而现在 pretext 帮我们找到了一个全新的解决方式。

什么是pretext?

pretext是一个纯 JS/TS 写的文本测量引擎,由知名开发者chenglou(React核心贡献者之一)推出。

它的核心理念很简单:让你不碰DOM就能精确知道文字会占多大空间
这个项目不是凭空出现的,它的设计思路可以追溯到Sebastian Markbage十年前的text-layout项目。
但pretext把这个想法推向了新的高度,支持了几乎所有你能想到的语言场景,处理了各种浏览器的 quirks。
pretext目前支持渲染到DOM、Canvas、SVG,未来还会支持服务端渲染。它把前端文本排版从浏览器的黑盒里解放出来,变成了可预测、可缓存的东西。

核心亮点

1️⃣ 不依赖DOM,零回流
pretext 完全绕过了DOM测量。
它用Canvas作为底层来测量文本宽度,但只在prepare阶段做一次,之后的所有layout都是纯算术运算。
这意味着你想测量多少次就测量多少次,完全不用担心性能问题。
2️⃣ 快到离谱的性能
官方基准测试数据:500段文本批量prepare()约19ms,layout()约0.09ms。
对比传统DOM测量,快了整整500倍!这个性能差异是什么概念?原本只能做几十次测量的预算,现在能做几万次。
3️⃣ 支持几乎所有语言
这是最让人惊叹的一点。
pretext支持中日韩、阿拉伯RTL、Emoji混排、混合双向文本,甚至处理了你不知道名字的语言。它还自动处理各种浏览器的quirks,保证在不同环境下结果一致。
4️⃣ AI友好的设计
pretext的实现方式特别适合AI迭代。
它用浏览器自己的字体引擎作为ground truth,可以快速迭代优化。在AI生成界面的时代,这种可预测的文本测量能力简直是基础设施级别的存在。

功能特性

pretext提供了两类API,满足不同的使用场景。
第一类:简单测量段落高度
这是最常用的场景,只需要两个函数:
prepare():做一次性的准备工作,包括归一化空白字符、分词、应用粘连规则、用Canvas测量分段,返回一个不透明的句柄。
layout():廉价的热路径,纯算术运算,基于缓存的宽度计算高度和行数。
比如在resize的时候,你只需要重新调用layout(),而不需要重新prepare(),性能完全不是问题。
第二类:手动布局段落行
如果你需要更精细的控制,比如让文字环绕图片、实现各种奇特的布局,pretext也提供了丰富的API:
prepareWithSegments():和prepare()类似,但返回更丰富的结构供手动布局使用。
layoutWithLines():给定固定宽度,返回所有行的信息。
walkLineRanges():遍历行范围,不构建文本字符串,适合做一些试探性的计算。
layoutNextLine():迭代器风格的API,允许每行用不同的宽度来布局。
这些API让你能实现任何你能想到的文本布局效果,比如文字环绕图片、瀑布流布局、动态调整每行宽度等等。

快速上手

安装

npm install @chenglou/pretext

最简单的用法:
测量段落高度,不碰DOM:

import { prepare, layout } from '@chenglou/pretext'

const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')
const { height, lineCount } = layout(prepared, 300, 20)

就是这么简单!没有DOM操作,没有回流,纯计算。
处理textarea风格的文本:
如果你需要保留空格、制表符和换行符:

const prepared = prepare(textareaValue, '16px Inter', { whiteSpace: 'pre-wrap' })
const { height } = layout(prepared, textareaWidth, 20)

手动布局行:
让文字环绕图片:

import { prepareWithSegments, layoutNextLine } from '@chenglou/pretext'

const prepared = prepareWithSegments('很长的文本...', '18px "Helvetica Neue"')
let cursor = { segmentIndex: 0, graphemeIndex: 0 }
let y = 0

while (true) {
  const width = y < image.bottom ? columnWidth - image.width : columnWidth
  const line = layoutNextLine(prepared, cursor, width)
  if (line === null) break
  ctx.fillText(line.text, 0, y)
  cursor = line.end
  y += 26
}

找到最合适的容器宽度
用walkLineRanges找到最宽的行,得到刚好能容纳文本的宽度:

let maxW = 0
walkLineRanges(prepared, 320, line => {
  if (line.width > maxW) maxW = line.width
})

其他辅助函数

import { clearCache, setLocale } from '@chenglou/pretext'

// 清除缓存,释放内存
clearCache()

// 设置语言环境
setLocale('zh-CN')

查看演示
你可以clone仓库运行演示:

git clone https://github.com/chenglou/pretext
cd pretext
bun install
bun start

然后打开浏览器访问/demos(注意不要加末尾斜杠)。或者直接访问在线演示:chenglou.me/pretext

为什么受到这么多关注?

pretext的出现,代表着前端开发的一个重要转变。它把原本封闭在浏览器内部的文本排版能力,以一种可预测、可缓存的方式暴露给了开发者。
这解锁了太多可能性:
• 完美的虚拟滚动,不需要猜测高度
• 复杂的用户自定义布局,不再需要CSS hack
• AI生成界面时,可以准确预测排版结果
• 开发时可以在浏览器外验证文本不会溢出
• 加载新内容时,可以防止布局偏移
在AI生成界面的时代,这种能力简直是基础设施级别的。你可以想象,未来的AI界面生成器,会大量依赖这样的库来保证生成的界面是正确的。

写在最后

pretext是一个革命性的文本测量引擎,它让前端开发者终于摆脱了DOM测量的性能桎梏。
500倍的性能提升,全语言支持,零回流操作——这每一点都足够让人兴奋。
如果你正在做虚拟滚动、复杂排版、或者任何需要频繁测量文本的应用,pretext绝对值得你加入技术栈。它不仅能提升性能,更能让你的代码变得更简洁、更可维护。
最后,别忘了去GitHub给这个项目点个Star,支持一下这些默默为前端社区做贡献的开发者们!
**GitHub:**https://github.com/chenglou/pretext

推荐文章

程序员茄子在线接单