
前端里有一类问题看起来很普通,但真做起来会非常磨人:一段多语言文本放进某个宽度后到底会换成几行、占多高、最宽的那一行有多宽?最直接的做法是把内容塞进 DOM,再读 getBoundingClientRect、offsetHeight 之类的值;问题是这些读取会触发布局计算,在虚拟列表、聊天气泡、编辑器、复杂卡片流里很容易变成性能热点。
Pretext 就是为这个窄而硬的问题做的开源库。它是一个纯 JavaScript/TypeScript 的多行文本测量与排版库,目标是在不走 DOM reflow 热路径的情况下,提前算出文本高度、行数、行宽和换行范围。项目目前在 GitHub 上约 47.3k stars,MIT 许可证,npm 包名是 @chenglou/pretext,最新版本为 0.0.7。
它绕开的,是浏览器里最贵的那类测量
Pretext 的核心思路不是自己造一个完整字体渲染引擎,而是把浏览器自己的字体测量结果作为 ground truth:先用 prepare() 做一次文本预处理,完成空白归一化、分段、glue 规则和 canvas 宽度测量;后续在 resize 或不同容器宽度下,只需要调用 layout() 做便宜的算术计算,返回 height 和 lineCount。
这对 UI 性能很实际。比如虚拟列表里要提前知道消息气泡高度,瀑布流里要安排文字卡片,或者 AI 辅助生成界面时想在浏览器外验证按钮标签会不会溢出,都可以先用 Pretext 算一遍,而不是让页面不断插入隐藏节点、读取尺寸、再触发布局。
从测高度到自己排每一行
如果只是想知道“这段文字在 320px 宽、20px 行高下有多高”,prepare() 加 layout() 已经够用。更有意思的是第二类用法:切到 prepareWithSegments() 后,可以用 layoutWithLines() 拿到每一行文本,也可以用 measureLineStats()、walkLineRanges() 在不创建字符串的情况下读取行数和最大行宽。
这种能力会打开一些浏览器默认布局不太好表达的场景:让文本围绕图片或障碍物逐行流动、寻找刚好能包住多行文字的紧凑宽度、在 Canvas / SVG / WebGL 里自己渲染段落,或者做 rich inline flow,让 code span、mention、chip 这类内联元素保持原子性,同时又让普通文本正常换行。
边界也写得很清楚
Pretext 不是 CSS inline formatting engine 的完整替代品,它当前覆盖的是常见文本设置:white-space: normal 和 pre-wrap,word-break: normal 和 keep-all,以及数值型 letter-spacing。它依赖 Intl.Segmenter 和 Canvas 2D 文本测量;README 也提醒,在 macOS 上为了准确性不要直接用 system-ui,最好传入明确的字体名。
我觉得它最值得关注的地方,是把“文本布局预测”从靠 DOM 试出来,变成一个可以被缓存、推演和测试的普通函数调用。对于聊天、文档、设计工具、数据密集型前端和 Canvas/SVG 渲染来说,这个小切口很可能正好切到性能和体验的痛点。
项目地址
官网:https://chenglou.me/pretext/
项目地址:https://github.com/chenglou/pretext
原创文章,如若转载,请注明出处:https://wefound.cc/p/3277.html