Pretext 核心是完全绕过 DOM,通过 “两阶段计算” 实现极速文本测量与换行。
一、底层逻辑:两阶段架构(核心)
Pretext 把 “慢操作” 和 “快操作” 彻底分离:
- 冷路径(prepare) :一次性、昂贵的预处理
- 热路径(layout) :纯算术、极速的布局计算
1. 冷路径:prepare () — 预处理(只做一次)
核心:用 Canvas 测宽 + 分词缓存
- 文本分词:用
Intl.Segmenter按 “语义单元” 拆分(英文单词、中文单字、emoji、组合字符) - Canvas 测量:调用
canvas.measureText()测每个单元的精确宽度(不触发 DOM 重排) - 缓存:把所有单元宽度、字体信息缓存成一个
prepared句柄 - 规范化:处理空白、换行、双向文本(Bidi)、浏览器差异
2. 热路径:layout () — 布局计算(无限次复用)
核心:纯数学模拟浏览器换行
- 输入:
prepared句柄 + 容器宽度 + 行高 - 输出:总高度、行数、每行内容、换行位置
- 原理:贪心算法 + 必要回溯,模拟 CSS
white-space: normal换行规则 - 性能:≈0.09ms / 次(传统 DOM 测量 ≈0.5–2ms / 次,快 10–20 倍)
二、核心优势
- 零 DOM、零重排:不碰
getBoundingClientRect、不触发 Reflow - 极致性能:prepare 一次,layout 微秒级
- 跨浏览器一致:抹平 Chrome/Safari/Firefox 排版差异
- 全语言支持:中英日韩、阿拉伯、emoji、双向文本(Bidi)
三、代码实例(快速上手)
1. 基础:测量文本高度
javascript
运行
import { prepare, layout } from '@chenglou/pretext'
// 1. 冷路径:一次性准备(文本/字体变了才重做)
const prepared = prepare(
'Pretext 是前端高性能文本布局库,完全绕过 DOM,两阶段计算。',
'16px Inter, sans-serif' // 字体样式(同 CSS font 简写)
)
// 2. 热路径:任意宽度、任意次数计算(极速)
const result1 = layout(prepared, 300, 24) // 宽300px,行高24px
console.log('300px宽:', result1.height, 'px,', result1.lineCount, '行')
const result2 = layout(prepared, 500, 24) // 宽500px
console.log('500px宽:', result2.height, 'px,', result2.lineCount, '行')
2. 进阶:获取每行内容(虚拟列表 / 流式渲染)
javascript
运行
const { lines } = layout(prepared, 350, 24)
// lines 数组:每一行的文本片段
lines.forEach((line, i) => {
console.log(`第${i+1}行:`, line.text)
})
3. 响应式布局(窗口 resize)
javascript
运行
function update() {
const containerWidth = document.getElementById('text').clientWidth
const { height } = layout(prepared, containerWidth, 24)
document.getElementById('text').style.height = `${height}px`
}
// 窗口变化时,纯计算更新,无 DOM 测量
window.addEventListener('resize', update)
update()
四、适用场景(性能敏感)
- 虚拟列表(长文本、聊天记录)
- AI 流式打字 / 逐字渲染
- 响应式卡片 / 富文本高度计算
- 动画中动态文本尺寸
- 跨端一致排版(Web/Node/Worker)
五、与传统 DOM 测量对比
表格
| 方式 | 原理 | 性能 | 重排 | 跨浏览器 |
|---|---|---|---|---|
| Pretext | Canvas 缓存 + 纯计算 | 0.09ms | ❌ 无 | ✅ 一致 |
DOM + getBoundingClientRect | 渲染 → 测量 | 0.5–2ms | ✅ 有 | ❌ 差异大 |
一句话总结:Pretext = 一次 Canvas 测量 + 无限次纯数学换行,把文本布局从 DOM 瓶颈中解放出来。