最近,一个名为 Pretext 的开源项目在前端社区引起了关注。这是一个用 TypeScript 编写的文本排版引擎,专注于解决一个具体问题:在不触发布局重排(reflow)的前提下,准确测量多行文本的高度

项目作者是 Cheng Lou,他曾是 React 核心团队成员,项目上线后,目前在 GitHub 上获得了30.2k的Star。

乍一看名字,可能以为又是个新框架或者编译工具,点进去才发现——原来是个文本排版库。

但它解决的那个问题,很多前端开发者应该都遇到过。

Pretext效果

先来看看作者是怎么说的:

Pure JavaScript/TypeScript library for multiline text measurement & layout. Fast, accurate & supports all the languages you didn't even know about. Allows rendering to DOM, Canvas, SVG and soon, server-side.

纯 JavaScript/TypeScript 库,用于多行文本测量与排版。速度快、精度高,支持各种你可能都没听说过的语言。可渲染到 DOM、Canvas、SVG,即将支持服务端渲染。

Pretext side-steps the need for DOM measurements (e.g. , ), which trigger layout reflow, one of the most expensive operations in the browser. It implements its own text measurement logic, using the browsers' own font engine as ground truth (very AI-friendly iteration method).getBoundingClientRectoffsetHeight

Pretext 绕开了 DOM 测量的需求(例如 getBoundingClientRectoffsetHeight),因为这些操作会触发布局重排(reflow),这是浏览器中最耗时的操作之一。它实现了自己的文本测量逻辑,以浏览器自身的字体引擎作为基准(这是一种对 AI 非常友好的迭代方法)。

一个老生常谈的痛点

当你要做一个聊天列表、评论流,或者任何需要虚拟滚动的长列表时,有一个绕不开的步骤:你需要知道每一条消息文本到底有多高

最朴素的做法是:把文字塞进一个隐藏的 DOM 元素里,然后用 getBoundingClientRect 或 offsetHeight 去量。

这招能用,但有个代价。这两个 API 一调用,浏览器就得停下手里的事情,重新计算整个页面的布局——这个过程叫 reflow(回流)。偶尔量一次没什么,但如果你要同时量几百条消息,性能就肉眼可见地往下掉。浏览器一帧只有 16.6ms,量一次可能就吃掉几十毫秒,滑动起来就是一卡一卡的。

更麻烦的是,这种“先渲染再测量”的模式,写起代码来也容易把测量逻辑和渲染逻辑搅在一起。

Pretext 的思路:把“测量”和“布局”拆开

Pretext 的做法很简单:重活只做一次,后续都是纯数学计算

它把整个过程拆成两步:

1. prepare() —— 一次性预处理

这一步会做几件事:

  • 文本规范化(处理空白符)

  • 用 Intl.Segmenter 分词(支持各种语言和 emoji)

  • 用 Canvas 的 measureText 量出每个片段的宽度

  • 把结果缓存起来

这一步相对重一些,但只做一次。官方给了一个 benchmark 数据:处理 500 段文本,大约 19ms

2. layout() —— 轻量布局计算

拿到缓存的宽度数据后,给定一个容器宽度,它就能算出换行和总高度。

这一步完全不碰 DOM,就是纯算术运算,非常快。同样 500 段文本,只要 0.09ms

这就意味着,你可以放心地在窗口大小变化、侧边栏拖拽等场景下反复调用 layout(),不用担心卡顿。

它能用在哪儿?

从项目的 demo 和社区讨论来看,这几个场景比较典型:

  • 虚拟滚动列表:提前知道每一项的高度,滚动时精确控制渲染范围,避免卡顿。

  • 自适应聊天气泡:根据文本内容算出最紧凑的宽度,不用等 DOM 渲染完再去量。

  • Canvas / SVG 复杂排版:比如文字绕图、多栏杂志布局,以前用 CSS 很难做,现在可以自己控制每一行的输出。

  • 服务端渲染(未来):目前 prepare 依赖 Canvas,但作者计划支持纯服务端环境,届时可以在 Node 里直接算好布局返回给前端。

还有一个有意思的方向:AI 生成 UI。如果 AI 能直接调用一个纯函数,输入文字和容器宽度,输出精确高度,那它就不用去猜 CSS 的盒模型了。Pretext 这种确定性接口对 AI 确实友好。

API 设计

Pretext 提供了两套 API,分别对应不同需求。

基础用法:仅需高度

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

// 预处理:传入文本和字体
const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')

// 布局计算:给定宽度和行高
const { height, lineCount } = layout(prepared, 300, 20)

高级用法:逐行控制

如果需要手动控制每一行的输出(例如实现文字绕图),可以使用 prepareWithSegments 配合迭代式 API:

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

const prepared = prepareWithSegments(text, '18px "Helvetica Neue"')
let cursor = { segmentIndex: 0, graphemeIndex: 0 }
let y = 0

while (true) {
  // 根据当前 y 坐标决定可用宽度
  const width = y < imageHeight ? columnWidth - imageWidth : columnWidth
  const line = layoutNextLine(prepared, cursor, width)
  if (!line) break
  
  // 渲染当前行(可输出到 Canvas、SVG 等)
  ctx.fillText(line.text, 0, y)
  cursor = line.end
  y += lineHeight
}

其他高级 API 还包括:

  • layoutWithLines():一次性获取所有行信息

  • walkLineRanges():在不构建字符串的情况下遍历行范围,可用于二分搜索最优宽度

多语言与排版规则

Pretext 的目标是复现浏览器的默认排版行为。根据项目文档,它支持:

  • 从左到右(LTR)与从右到左(RTL)双向文本混合

  • 多种语言的断行规则(中文、日文、阿拉伯语等)

  • Emoji 与组合字符(grapheme)处理

排版行为以浏览器的实际渲染结果为基准,通过大量测试用例(项目中的 corpora/ 目录)进行验证和对齐。

项目文档中也列出了当前支持的范围:

  • white-space: normal 或 pre-wrap

  • word-break: normal

  • overflow-wrap: break-word

  • line-break: auto

使用注意事项(我照搬了作者的说明)


Pretext还没试图成为一个完整的字体渲染引擎(至少现在还没?)。目前它主要针对通用文本设置:

white-space: normal
word-break: normal
overflow-wrap: break-word
line-break: auto

如果传入 { whiteSpace: 'pre-wrap' },普通空格、制表符 \t 和硬换行 \n 会被保留,而不是折叠。制表符宽度遵循浏览器默认的 tab-size: 8。其他断行规则保持不变:word-break: normaloverflow-wrap: break-wordline-break: auto

macOS 上使用 system-ui 会影响 layout() 的精度,建议指定具体字体。

由于默认包含 overflow-wrap: break-word,在极窄宽度下可能会在字形边界断行。


system-ui在macOS上对准确性不安全。使用命名字体。layout()
由于默认目标包括 ,非常窄的宽度仍可能在字形边界处破损。overflow-wrap: break-word

小结

Pretext 并不算 “颠覆性框架”,但它精准解决了一个长期存在的前端问题:在不触发重排的前提下,高效、精确地测量多行文本高度。

它通过 “重预处理 + 轻布局计算” 的分离设计,用数据对齐方式复刻了浏览器复杂排版行为,并对外提供一套简洁、高性能的 API。如果你正在做虚拟滚动、Canvas 排版,或需要为 AI 生成 UI 提供可靠布局计算,它会是一个非常实用的工具。

(目前 Star 已突破 30k,且仍在持续增长)

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐