今天介绍一个看似小众但实际应用场景非常广泛的开源库——Pretext。这是一个纯 JavaScript/TypeScript 编写的多行文本测量和布局库,可以在不触碰 DOM 的情况下精确测量文本高度和行数。
项目地址:https://github.com/chenglou/pretext
解决的问题
在 Web 开发中,文本测量是一个看似简单实则麻烦的问题。常见做法是先把文本放到 DOM 里,然后用 getBoundingClientRect 或 offsetHeight 来测量高度。但这样做的问题在于:DOM 测量会触发浏览器重排(layout reflow),这是浏览器中最昂贵的操作之一,严重影响渲染性能。
Pretext 的解决方案是:自己实现文本测量逻辑,以浏览器自身的字体引擎为基准,在 Canvas 上测量每个文本片段的宽度,然后通过纯算术计算来预测给定宽度下的行数和高度。整个过程完全不触碰真实 DOM,不触发任何重排。
核心 API
Pretext 有两大使用场景:
场景一:测量段落高度(无需触碰 DOM)
import { prepare, layout } from ‘@chenglou/pretext’
const prepared = prepare(‘AGI 春天到了. بدأت الرحلة 🚀’, ’16px Inter’)
const { height, lineCount } = layout(prepared, textWidth, 20)
// 纯算术计算,无 DOM 布局和重排!
prepare() 函数做一次性工作:规范化空白、分段文本、应用胶水规则、在 Canvas 上测量各片段宽度,返回一个不透明句柄。layout() 是后续的热路径:基于缓存的宽度进行纯算术计算。请勿对相同文本和配置重复运行 prepare(),否则会丧失预计算的优势。
场景二:手动布局段落行
import { prepareWithSegments, layoutWithLines } from ‘@chenglou/pretext’
const prepared = prepareWithSegments(‘AGI 春天到了.都开始旅程 🚀’, ’18px Helvetica Neue’)
const { lines } = layoutWithLines(prepared, 320, 26)
// 320px 最大宽度,26px 行高
如果你需要渲染到 Canvas、SVG、WebGL 或未来的服务端渲染,这种方式非常有用。layoutWithLines() 给出固定宽度下的所有行;measureLineStats() 和 walkLineRanges() 给你行数、最大行宽等信息;layoutNextLineRange() 允许你动态改变宽度来逐行路由文本——比如实现文字绕排浮动图片的效果。
安装步骤
npm install @chenglou/pretext
或者使用 Bun:
bun add @chenglou/pretext
特色功能
预计算 + 热路径分离:prepare() 只运行一次,结果可复用,layout() 调用极快。
多语言支持:支持包括阿拉伯语、希伯来语、中文、日文在内的所有语言,使用浏览器原生字体引擎作为基准。
多种输出目标:DOM、Canvas、SVG 以及未来的服务端渲染。
丰富的布局控制:wordBreak、whiteSpace 等 CSS 类似选项,textarea 风格预格式化文本支持。
使用场景
虚拟列表/无限滚动:精确知道每项高度,无需猜测或缓存。
动态内容页面:防止新文本加载时的布局跳动(CLS),提前锚定滚动位置。
Canvas/SVG 文本渲染:精确分行,不依赖 DOM。
文字绕排:实现图片旁边文字窄列、动态调整宽度的效果。
AI 生成内容验证:在 AI 生成标签、按钮文字时,提前验证是否溢出,不必等待浏览器渲染。
服务端渲染:未来的服务端支持让 Node.js 环境也能做精确文本测量。
适用人群
需要高性能文本渲染的 Web 应用开发者;对页面性能(特别是 CLS 指标)有严格要求的开发者;实现 Canvas 或 SVG 复杂文本布局的开发者;在服务端需要精确文本测量的 Node.js 应用开发者;AI 生成 UI 时需要预验证文本布局的自动化工具开发者。
开源协议:MIT 协议。
总结
Pretext 是一个看起来「小众」但实际上需求广泛的基础设施型库。Chenglou 在开源社区有很高的声誉(曾在 React 核心团队工作),代码质量有保证。如果你做过复杂的多行文本布局,特别是涉及到性能敏感的 DOM 环境,Pretext 值得一试。
服务支持:如有兴趣不会搭建,可以联系微信:WRYD6166,开源项目搭建10-50元。









暂无评论内容