上萬圖層也不卡頓:Figma 重寫圖層面板的兩個關鍵修法

七年前寫的圖層面板開始卡。Figma 用兩段式計算與衍生屬性快取砍掉重練,最大最複雜的檔案互動快了 30-50%——而且不只面板,整個編輯器都跟著順。

Improving performance in the layers panel | Figma 官方文章封面

你可能沒注意過圖層面板(layers panel),但你每天都在用它。左側那條巢狀的清單,是一個 Figma 檔案的藍圖——所有 frame、群組、元件、文字,全攤在那裡。

問題是,這個面板是將近七年前寫的,那時候的檔案小、功能少。七年後,一個檔案裡塞上萬個圖層已經是日常。於是它開始卡:展開一個群組要等、拖拉物件會頓、連打字都慢半拍。Figma 工程團隊乾脆把它砍掉重練,結果是在最大、最複雜的檔案裡,互動快了 30 到 50%。

Figma Blog · 原文出處
Improving performance in the layers panel
Shannen Wu & Peter Hayes · Inside Figma · 2026/06/11
讀英文原文 →
舊架構卡在兩件事
算太多
面板一次替所有展開的圖層算資料——可能上萬列。但你的螢幕一次只看得到 20–30 列
算太頻繁
幾乎沒做快取。展開一個群組這種小動作,就要把整棵樹從頭重算一遍。
前言

先講清楚這個面板在做什麼。Figma 檔案本質上是一棵節點樹(tree of nodes),結構跟 HTML 很像:每個節點有自己的屬性(名稱、是否可見等),底下掛著一串子節點。要把這棵樹畫成左側那條清單,Figma 得組出一個龐大的 JavaScript 物件,裝進每個節點的所有資料。

舊做法是「一趟掃完」:從當前頁面的每個頂層節點出發,收集它的資料;如果它是展開的,就遞迴鑽進子節點,再收集、再鑽進去。檔案一大、展開的節點一多,這趟掃描就重得離譜——而且每次面板有任何變動,整件事就重來一次。

Figma 圖層面板的相依關係圖
光是「該顯示哪幾列」就牽動一整張相依網:autolayout 子層要反序、widget 不顯示子層、原型 frame 要拆固定與捲動區段、頂層 frame 要 sticky。圖|Figma
01 / 04 第一修:把計算切成兩段

要治「算太多」,團隊把收集資料的過程拆成兩趟。

第一趟,只算出「面板上該出現哪幾列、順序是什麼」這一份 row ID 清單,其他資料先全部擱著。別小看這份清單——光是排序就一堆眉角:autolayout frame 的子層要反序顯示、widget 跟 FigJam 便利貼不顯示子層、原型 frame 的固定與捲動區段要拆成兩塊、頂層 frame 要 sticky 釘住。

第二趟才去算每一列真正要顯示的東西:名稱、圖示、鎖定狀態、可見性、選取狀態。關鍵在於,有了第一趟的 ID 清單,第二趟只需要替「視窗內」那幾十列算資料。這個技巧叫 windowing(視窗化)——捲動清單只渲染螢幕上看得到的項目。舊架構其實也有 windowing,但因為全擠在一趟算,連看不到、根本不渲染的列也照算不誤。

Try this
大檔案開始頓的時候,先把暫時不看的區塊收合起來。展開越少節點,面板要處理的列就越少——這跟 Figma 內部的 windowing 是同一個道理:螢幕看不到的,就別讓它佔資源。
02 / 04 第二修:只重算有變動的那一塊

治「算太頻繁」,靠的是 Figma 這幾年累積的底層機制:衍生屬性(derived properties)。

道理跟試算表很像。節點有些值是直接存的(像相對位置),有些值則是「從別的值算出來的」。例如一個節點的絕對位置,Figma 不直接存,而是用「父層絕對位置 + 自己的相對位置」現算——這樣移動或旋轉一整群物件才方便。衍生屬性把這種「A 由 B、C 算出來」的關係正式宣告出來,系統就會自動追蹤相依、需要時才重算,跟試算表裡一格公式引用其他格一模一樣。

套到圖層面板上,好處立刻浮現:以前樹裡任何地方一變,整棵樹重算;現在每個節點都知道自己依賴誰,只有「真的受影響的那一小段」需要更新。展開 Frame B,就只重算 A 到 B 這條路徑,旁邊 Frame C 底下那 100 個子層完全跳過。再加上衍生屬性預設「懶算」(lazy)——沒被展開、沒人讀取,它就永遠不算。

圖層快取的視覺化
只重畫真正變動的圖層、其餘維持不動,就能避免一遍又一遍做昂貴的重算。圖|Figma
Try this
「只動有變的那塊」也是你建檔案時該追求的結構。善用 component、Auto Layout、variables,讓 Figma 清楚知道元素之間的依賴關係——結構越乾淨,工具越能只更新該更新的部分,而不是每次都重算整頁。
03 / 04 快取的代價:記憶體怎麼省

快取一定會吃記憶體。小幅增加換來大幅提速,划算;但吃過頭就會冒出「記憶體不足」的錯誤,那種體驗很折磨人。

問題出在天真的快取寫法:每一層都把底下所有後代的 ID 存一份,記憶體成本會像三角數一樣累加(1 + 2 + … + n,等於 n(n+1)/2),也就是 O(n²)。在很深的樹裡,這可能膨脹到數十 MB,不能接受。

團隊改用一種類似 rope 的遞迴結構來存這份排序清單。rope 是把序列拆成小片段的樹狀結構,編輯或串接時可以重用既有片段,不必整串重建。關鍵在於它用指標(pointer)組合、而非整份複製,最大化「結構共享」。代價只是讀取時要多走幾步指標,換來記憶體用量從 O(n²) 降到嚴格的 O(n)——比最初原型省下最多 99% 記憶體。

Try this
就算工具優化到位,超大檔案還是會吃資源。養成歸檔習慣:把不再動的舊頁面、廢棄探索分到獨立檔案,主檔保持精簡。對團隊協作檔尤其有感。
04 / 04 成果:不只面板變快

兩招下來,效益很明確。展開/收合列、切換可見性或鎖定這類核心互動,在最大、最複雜的檔案裡快了將近 30 到 50%。

更有意思的是漣漪效應。圖層面板省下的不必要運算,回饋到整個 Figma 編輯器——整體渲染變順、FPS 提高、卡頓的影格變少。於是那些原本「在複雜檔案裡明顯黏滯」的動作,像打字、拖拉、選顏色,現在都穩定流暢了。一個藏在側邊欄的元件,優化得當,居然能讓整個畫布跟著呼吸順暢。

整體觀察

這篇拆的是工程細節,但底層的兩個原則,任何天天開大檔案的人都用得上:只做「看得到的部分」的工,只重算「真的變了的那塊」。windowing 對應的是收合不看的圖層,衍生屬性對應的是用乾淨結構讓工具知道誰依賴誰。工具在底層替你省力,你在上層把檔案整理乾淨,兩邊才會合拍。

Windowing means we cut away everything outside the viewport, and only focus on what's inside.
— Shannen Wu & Peter Hayes, Figma Engineering
重點整理
01舊圖層面板兩個病灶:替所有展開節點算資料(算太多)、任何變動就整棵樹重算(算太頻繁)。
02兩段式計算 + windowing:先算 row ID 清單,再只替螢幕看得到的幾十列算資料。
03衍生屬性快取:像試算表公式追蹤相依,只重算受影響的子樹,預設懶算。
04用類 rope 結構控記憶體,從 O(n²) 降到 O(n),省下最多 99%;最終大檔案互動快 30–50%。
— · —
Figma 全攻略
大檔案不卡頓,從結構乾淨開始
Figma 的優化幫你省底層運算,但檔案結構乾不乾淨是你的事。從 component、variables、Auto Layout 的底層邏輯,到大型 design system 的組織方法,一次練到能駕馭上萬圖層的檔案。
看課程 →
AI 覺醒設計應用攻略
把 AI 變成你的設計第二大腦
每週更新的 AI 設計應用攻略,從工具串接到工作流重組,帶你把最新的 AI 能力真正接進日常設計流程。
了解訂閱 →