Pretext-前端高性能文本布局库

2 阅读2分钟

Pretext 核心是完全绕过 DOM,通过 “两阶段计算” 实现极速文本测量与换行

一、底层逻辑:两阶段架构(核心)

Pretext 把 “慢操作” 和 “快操作” 彻底分离:

  • 冷路径(prepare) :一次性、昂贵的预处理
  • 热路径(layout) :纯算术、极速的布局计算

1. 冷路径:prepare () — 预处理(只做一次)

核心:用 Canvas 测宽 + 分词缓存

  1. 文本分词:用 Intl.Segmenter 按 “语义单元” 拆分(英文单词、中文单字、emoji、组合字符)
  2. Canvas 测量:调用 canvas.measureText() 测每个单元的精确宽度(不触发 DOM 重排
  3. 缓存:把所有单元宽度、字体信息缓存成一个 prepared 句柄
  4. 规范化:处理空白、换行、双向文本(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 测量对比

表格

方式原理性能重排跨浏览器
PretextCanvas 缓存 + 纯计算0.09ms❌ 无✅ 一致
DOM + getBoundingClientRect渲染 → 测量0.5–2ms✅ 有❌ 差异大

一句话总结:Pretext = 一次 Canvas 测量 + 无限次纯数学换行,把文本布局从 DOM 瓶颈中解放出来。