无需触碰 DOM
Pretext.js 完全通过算术运算来测量和排版多行文本 — 无 getBoundingClientRect,无回流,无抖动。首次调用即快速,后续调用瞬间完成。
每当你的 JavaScript 在 DOM 节点上调用 getBoundingClientRect()、offsetHeight 或 scrollHeight 时,浏览器必须暂停脚本执行、刷新所有待处理的样式更改,并执行完整的布局计算 — 仅仅是为了回答一个关于盒子大小的问题。
这被称为强制同步回流,是浏览器能执行的最昂贵的操作之一。在紧凑的循环中 — 比如测量虚拟滚动列表中的上千个项目 — 它会导致抖动:浏览器在渲染和 JavaScript 执行之间反复切换数百次,即使是现代硬件也会被拖慢。
讽刺的是,大多数时候你只需要一个数字:给定容器宽度,这段文本会有多少像素高?这个问题根本不需要触碰 DOM。pretext.js 的存在就是为了证明这一点。
// 每次迭代都会强制浏览器布局 const heights = items.map((item) => { const el = createElement(item.text); document.body.appendChild(el); // ← 在此处强制布局回流 const h = el.getBoundingClientRect().height; reflow! document.body.removeChild(el); return h; }); // 1000 个项目 = 1000 次回流 = ~94ms ≈ 丢失 6 帧
拖动分隔线对比传统 DOM 方法与 Pretext.js。一个每次调用都触发回流,Pretext.js 使用纯算术运算。
import { prepare, layout } from '@chenglou/pretext' // prepare() 只运行一次 — 使用 Canvas const prepared = prepare( 'The quick brown fox jumped.', '16px Inter' ); // layout() 是纯算术运算 const { height, lineCount } = layout( prepared, containerWidth, lineHeight ); 无回流 // 1000 个项目 = 0 次回流 = ~0.05ms // 快 500 倍,零 DOM 访问
// 每次迭代都会强制浏览器布局 const heights = items.map((item) => { const el = createElement(item.text); document.body.appendChild(el); // ← 在此处强制布局回流 const h = el.getBoundingClientRect().height; reflow! document.body.removeChild(el); return h; }); // 1000 个项目 = 1000 次回流 = ~94ms // ≈ 在 60fps 下丢失 6 帧
标准化空白字符,应用 Unicode 换行规则,使用浏览器自身的文本分割功能将字符串分割为可测量的单元。
将每个片段通过 Canvas measureText() 获取字体引擎的真实字形前进宽度。结果会被缓存。
给定容器宽度,通过累加片段宽度计算换行点。行数乘以行高即得高度。完全不需要 DOM。
pretext.js 专为构建复杂、文本密集型 UI 的开发者设计,传统 DOM 测量已成为瓶颈。这些能力让它可以投入生产。
在 Pretext.js 中,prepare() 之后每次 layout() 调用都是纯算术运算。不使用 getBoundingClientRect,不读 offsetHeight,不触发强制同步回流。
Pretext.js 使用浏览器自身的 Canvas 字体引擎测量字形宽度,而非启发式方法或查找表。结果与浏览器实际渲染完全匹配。
Pretext.js 完整支持中日韩、阿拉伯语、希伯来语、泰语、印地语和韩语书写系统,包括正确的 Unicode 分段和双向文本处理。
从零开始用 TypeScript 编写。每个函数、参数和返回值都有精确的类型定义 — 无需 @types 包,无需类型体操。
一次 prepare() 调用覆盖所有容器宽度。从同一个句柄出发,三次算术运算即可计算移动端、平板和桌面端的高度。
没有外部包,没有 polyfill,bundle 中没有意外。Pretext.js 完全依赖每个现代环境中都可用的标准浏览器 API。
Pretext.js 在传统 DOM 测量失效的场景中表现最为出色。这些示例展示 Pretext.js 如何解决真实的生产挑战 — 从虚拟滚动到多语言聊天界面。
渲染 10,000 个可变文本高度的列表项,完全无需 DOM 读取。在任何设备上都能实现 60fps 的流畅滚动。
使用 Pretext.js 在 AI 流式响应渲染完成前预先计算气泡高度。彻底消除聊天界面中的偏移和跳动。
在单个虚拟化列表中混合中文、阿拉伯文、韩文和拉丁文的社交信息流。每种脚本都能准确测量,无需特殊处理。
pretext.js 已发布到 npm,附带完整的 TypeScript 声明。用你喜欢的包管理器安装,导入两个函数,就可以开始无需 DOM 的文本测量了。
import { prepare, layout } from '@chenglou/pretext' // 步骤 1: 为给定的文本 + 字体对 prepare 一次 const handle = prepare( 'Hello, pretext.js — no reflow needed.', '16px "Inter"' ); // 步骤 2: 以任何宽度即时 layout const { height, lineCount } = layout( handle, 400, // 容器宽度 (px) 24 // 行高 (px) ); console.log(height); // → 48 console.log(lineCount); // → 2 // 步骤 3: 复用 handle 用于不同宽度 const narrow = layout(handle, 240, 24); // → 3 行
深入探讨文本渲染、浏览器性能,以及 Pretext.js 如何解决开发者每天都会遇到的问题 — 即使他们不知道根本原因。
详细了解调用 getBoundingClientRect 时浏览器内部发生了什么 — 哪些子系统被激活,为什么传统模型中同步回流不可避免,以及 Pretext.js 如何通过 Canvas 测量完全绕过这个问题。
一步步指导如何将 pretext.js 接入 React 虚拟化列表组件。涵盖 prepare 缓存策略、动态字体加载处理,以及容器宽度变化时该怎么做。
最新版本改进了 Chrome 和 Safari 上的中文字符间距精度,增加了完整的 white-space: pre-wrap 支持,并提供了新的 clearCache() 工具函数。
无论你在构建虚拟滚动列表、代码编辑器、AI 聊天界面,还是任何文本高度很重要的应用 — Pretext.js 都能给你准确的测量结果,而没有性能代价。