一周狂攬40K+ Star⭐ 的 Pretext 到底有多誇張?

這週的前端圈,可以說是被一個叫 Pretext 的專案徹底洗版了。

短短幾天,GitHub 狂攬 41K+ Stars ⭐⭐⭐

很多剛入行的朋友看完官方那個極簡的 Readme 可能一頭霧水:不就是一個算文本長寬高的 JS 函式庫嗎?為什麼能火成這樣?CSS 的 word-wrapflex 難道不夠用嗎?

v2_741bc7c1a79445528b75ddc1980d6ccd@46958_img_gif.gif

v2_c43f8b79c3f6400d9a995d5f0adc869d@46958_img_gif.gif

v2_715e9ba3c8aa4ea7b8e1bc5b41f87ead@46958_img_gif.gif

但如果是被各種複雜表格、虛擬列表、Canvas 繪製折磨過的老兵,看到 Pretext 的那一刻,絕對會有一種激動。

因為這個函式庫,極其優雅地處理了前端效能優化裡最討厭、最頑固的問題——強制同步佈局(Forced Synchronous Layout)導致的重排(Reflow)。

今天,我們不念官方文件,結合我這幾年的修坑血淚史,聊聊這個 41K Star 的怪物到底解決了什麼世界級痛點,以及我們在真實業務裡該怎麼用它。


那些年用過的 getBoundingClientRect

前端開發有個大難題:一段動態文字渲染出來到底有多高?

設想一個極度真實的業務場景:你在做一個擁有十萬筆資料的 虛擬滾動列表(Virtual List)。為了讓列表順滑,你只能渲染視口內的那 20 條資料。問題是,每條資料裡的使用者評論長度不固定。有的人只發一句 哈哈😁,有的人發了 800 字的長文。在渲染之前,你必須提前知道每一行的高度,才能計算整個虛擬列表的滾動條位置和絕對定位的 top 值。

在 Pretext 出現之前,我們通常怎麼做?用的往往是最原始、極其粗暴的 離屏 DOM 測量法(Offscreen Measurement)

// 極其陰鬱的傳統測量法:DOM 測算
function measureTextHeightOldWay(text, width, fontSize) {
  // 1. 建立一個隱藏的 div
  const hiddenDiv = document.createElement('div');
  hiddenDiv.style.visibility = 'hidden';
  hiddenDiv.style.position = 'absolute';
  hiddenDiv.style.width = `${width}px`;
  hiddenDiv.style.fontSize = `${fontSize}px`;
  hiddenDiv.innerText = text;

  // 2. 強行塞入 DOM 樹
  document.body.appendChild(hiddenDiv);

  // 3. 讀取高度(災難的開始!!!)
  const height = hiddenDiv.offsetHeight; // 或者 getBoundingClientRect()

  // 4. 銷毀 DOM
  document.body.removeChild(hiddenDiv);

  return height;
}

程式看起來沒問題?但如果在初始化時,你在一個迴圈裡把這段程式跑了 1000 次,你的頁面會當場卡死白屏!

為什麼?因為瀏覽器底層是一個極度慵懶的系統。你操作 DOM 節點,它通常會先累積變更,等到這一幀結束再一次性繪製。但當你呼叫了 offsetHeightgetBoundingClientRect 時,瀏覽器為了給你一個最精確的值,會被迫打斷所有的優化,立即在主執行緒裡重新計算整個頁面的佈局(Reflow)。

你在迴圈裡呼叫 1000 次,瀏覽器就被迫重排 1000 次。這種 布局抖動(Layout Thrashing) 是前端效能的頭號殺手。


Pretext 的降維打擊 - 不碰 DOM,純數學演算

而 Pretext 的核心賣點,就寫在它的第一句介紹裡:純 JavaScript/TypeScript 函式庫,避免對 DOM 進行測量。

image.png

它完全摒棄了把元素塞進 DOM 裡量一下的笨方法。你要算這段文字佔據多少像素?好,你告訴我字型、字級、容器寬度,我直接在 JS 記憶體裡,透過底層的文字排版演算法,硬生生給你出來!

我們直接看程式碼,看看接入 Pretext 之後,世界變得多清爽:

// 使用 Pretext
import { measureText } from 'pretext';

function measureTextHeightNewWay(text, containerWidth) {
  // 沒有任何 DOM 操作!直接傳入參數計算
  const metrics = measureText(text, {
    fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto',
    fontSize: 14,
    lineHeight: 1.5,
    maxWidth: containerWidth,
    // 甚至支援複雜的換行策略
    wordBreak: 'break-word',
  });

  // 直接拿到精準的寬高和行數!
  return metrics.height;
}

對比一下,這帶來了什麼工程級別的質變?

  • 快到離譜:因為不觸碰任何 DOM API,不會引起一絲一毫的瀏覽器重排。同樣的測量 1000 筆資料,用傳統 DOM 法可能需要 300ms(掉幀卡頓),用 Pretext 只需要 2ms。
  • 解鎖 Web Worker 潛能:以前因為要操作 DOM,測量文字的工作必須在瀏覽器的主執行緒(UI 執行緒)做,極容易阻塞頁面。現在它是純 JS 計算,你可以把十萬筆文本高度的計算邏輯丟到 Web Worker 裡去並行跑!主執行緒依然滑順如初。
  • 跨平台降維打擊:因為純 JS/TS,它不只在瀏覽器 DOM 裡能跑,也能在 Canvas 遊戲引擎裡跑、在 Node.js 的伺服端渲染(SSR)裡跑,甚至未來可以在 React Native 裡跑。

Pretext vs getBoundingClientRect 性能對比

image.png

更多好玩的 demo 👉:https://chenglou.me/pretext/

image.png

看似比較簡單,實則硬核的技術深水區

其實純 JS 估算文字這個想法,很多前端老手都想過。為什麼直到 2026 年,才被 Pretext 徹底做成一個 40K+ Star 的殺手級專案?

因為文字排版(Text Layout)是個深不見底的黑洞。

你以為算個寬度就是「字元數 × 字體寬度」?太天真了。你需要考慮英文單詞的斷詞(換行不能把單詞拆開)、需要考慮阿拉伯語的由右至左(RTL)、需要考慮中文的標點避頭尾規則、更別提那些五花八門的 Emoji(有的 Emoji 占好幾個位元組,但在螢幕上只是單一字元)。

更變態的是,不同瀏覽器(Chrome / Safari)底層的字型引擎(像 HarfBuzz 等)渲染規則都有細微差異。

Pretext 的作者 chenglou(曾參與 React Core,寫過 ReasonML 的大神👍👍👍)用了一種既聰明又符合現在 AI 時代的方法:將瀏覽器自身的字型引擎作為基準進行迭代對齊。

image.png

它沒有傻傻地重寫一套從零開始的渲染引擎,而是找到了一套能與主流瀏覽器高度擬合的純數學計算邏輯。精度極高,且非常輕量。

這不是在造輪子,這是在用極客思維給現有的前端標準打補丁。


那麼,哪些場景該果斷接入 Pretext?

雖然我把它吹爆了,但作為一個老油條,我必須負責任地告訴你:不要一時衝動,把專案裡所有普通的 CSS 排版都換成它。CSS 引擎依然是渲染標準流程最穩定、最簡單的方案。

Pretext 屬於極端場景的工具。遇到以下三種情況,直接掏出它:

  • 複雜資料看板 / 大規模動態虛擬列表:前面提到的,需要提前精確知道變長文字高度,來進行複雜絕對定位計算的場景。
  • Canvas / WebGL 富文本渲染:用過 Canvas 的人都知道,Canvas 裡的 fillText 非常原始,根本不支援自動換行。以前在 Canvas 裡畫多行文字簡直是噩夢,現在可以用 Pretext 算好每一行的位置,然後精確繪製。
  • 基於 Node.js 的海報/PDF 自動生成系統:伺服端沒有 DOM 環境,以前為了算文字是否會超出海報邊界,還得專門在伺服器上啟一個無頭瀏覽器(Puppeteer),非常耗資源。現在直接在 Node.js 引入 Pretext 做純端計算,一台 2 核機器能頂過去 8 核的併發量。

這才是前端該有的樣子🤔

這兩年,前端圈充滿了大模型、AI 生成程式碼的焦慮,似乎一切不加個 AI 前綴就不夠前沿。

但看到 Pretext 這種純粹為了解決計算機圖學底層痛點、逐行逐行扣效能、追求極致優雅的開源專案,短短幾天收穫 40K+ Star,我心裡其實挺欣慰的。

它證明了一件事:在花裡胡哨的概念之外,這個世界上永遠有那些扎根在工程最深處、被真實痛點折磨的開發者。

真正高階的前端工程能力,不是你接了多少個最新的大模型 API,而是當系統出現肉眼可見的卡頓時,精準指出那句藏在萬行程式碼裡的 offsetHeight,然後用純粹的數學與演算法,把頁面效能拉升兩個數量級。

週末了,別只顧著看熱鬧,去把 Pretext 拉下來,在本地建個 Canvas 或虛擬列表的 Demo 跑一跑。

那種看著耗時從 300 毫秒斷崖式下降到 2 毫秒的爽感,才是寫程式真正的樂趣😁。


原文出處:https://juejin.cn/post/7625904462995914803


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝9   💬9   ❤️3
514
🥈
我愛JS
📝2   💬7   ❤️2
150
🥉
💬1  
4
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登