一篇文件拆成幾萬張卡片:線上文件的 Block 架構,算的是前端工程的成本帳
一篇2026年10月底發布於掘金的技術長文,拆解線上文件Block架構的資料拍平與渲染成本設計,本文從前端工程成本與協同編輯的結構帳,看這套架構為何被採用。
刊登 閱讀約 4 分鐘
2026年10月26日,開發者「尤水就下」在掘金發表了一篇約22分鐘閱讀量的長文,主題是線上文件的 Block 架構如何實現。文章的起點很日常:一段下拉列表在大數據量下會把瀏覽器卡死,而當列表的每一項從純文字擴展為富文本與圖片時,這個問題的極限形態就是一份線上文件。這篇文章把那份極限形態背後的工程帳,逐項攤開。
問題的規模先擺出來
作者列出的問題清單,本質上都是同一類:資料規模超過了單次處理的經濟單位。文件在資料層可以直觀地表達為一棵巨大的嵌套 JSON,一個 Page 包含多個 Block,文字、圖片、圖表、程式碼、第三方元件都各是一個 Block。但這棵樹一旦長到幾萬個 Block,成本就從四面八方湧出來。
具體的問題包括:首屏必須等整份 JSON 下載解析完畢才能渲染;修改深層節點時定位開銷大;多人協同時難以精確描述「誰改了哪一塊」;同一份內容出現在多個位置只能靠複製資料;每輸入一個字都可能觸發整篇文件重渲染。這些問題疊加起來,構成了一套完整的成本結構:傳輸成本、解析成本、定位成本、衝突處理成本、渲染成本。
拍平:把文件樹拆成卡片
文章給出的核心改法是「資料拍平」。每個 Block 獲得一個穩定 id,所有 Block 平鋪進一個 recordMap,層級與順序關係改由 children 的 id 列表與 parentId 表達。用作者的說法,就是把文件樹拆成一張張卡片,再用 id 串起來。
這個改動的收益直接對應前述的成本項。局部更新時只需傳輸與重渲染被修改的那張卡片,而非整棵樹;協同編輯時,一個操作可以精確描述為針對某個 id 的 Block 的變更,衝突範圍被收斂到單一卡片層級;recordMap 是可拆的,這為分頁載入與壓縮提供了結構基礎,也解釋了為什麼文件還沒下載完,首屏已經可以看、甚至可以編輯。
從成本結構的角度看,這是一次典型的「把固定成本轉為變動成本」的工程決策。嵌套 JSON 的模式下,任何一次修改的成本都與整份文件的規模掛鉤;拍平之後,單次操作的成本只與被觸及的 Block 數量掛鉤。文件越大,兩種模式的成本差距越大。這與我們先前分析過的懶加載防抖方案的實測帳是同一條邏輯:渲染成本的控制點,永遠在「實際進入 DOM 的元素數量」這一欄。
這套架構為誰省錢
影響的傳導方向並不複雜。對產品方而言,Block 拍平加虛擬渲染直接決定了協同文件產品能否支撐長文件與多用戶場景,這是 Notion、飛書文件這類產品的基礎設施,不是附加功能。對第三方開發者而言,Block 作為統一介面(文字、圖表、程式碼、第三方元件都走同一套抽象)降低了插件與嵌入元件的接入成本。對終端用戶而言,收益表現為首屏速度與輸入流暢度,這兩項正是文件類工具留存與付費轉化的關鍵體驗指標。
承壓的一方則是工程團隊本身。作者在文中坦言,線上文件被前端圈視為技術天花板之一,資料拍平只是入場券,後面還有富文本輸入、協同編輯的一致性、虛擬布局、圖片載入後高度變化導致的頁面跳動等一系列系統性問題。每一項都是持續的維護成本,而非一次性投入。
一點保留
這篇文章的價值在於把架構決策還原為成本決策,資料結構怎麼設計,取決於你想把哪一類成本的單位縮小。不過文中內容屬於作者的實務經驗整理,涉及的效能描述未附基準測試數據,各家的具體實現(如 recordMap 的分片策略、協同演算法選型)也遠比文中展開的更複雜。讀者宜把它當作成本框架的入門帳本,而非可直接套用的實作規格。至於作者堅持手搓、AI 只當參考的立場,在程式碼生成工具快速滲透的當下,倒是另一條值得單獨算的帳。