三步驟加速你的網站效能
當網站商業邏輯中有需要大量頻繁的快速更新畫面,往往會遇到畫面卡頓的情況,這時候就需要工程師進行執行效能上的優化。那該如何進行網頁執行效能優化呢? 接下來會從 Reconciliation & Batch 概念解說開始,接著是運用 Chrome 開發者工具進行評估並進行
- 渲染優化 (Rendering Performance)
- 腳本效能優化 (JavaScript Performance)
如果還不太熟悉開發者工具的話,也可以先看看怎麼透過搶票按鈕來學習 Chrome 開發者工具除錯技巧 (Debug)。
Reconciliation & Batch 概念理解
當資料更新時,從解析 HTML + CSS 變成實際畫面的過程後會產生 Render Tree,接著經過 reFlow 計算出 Render Tree 上各個元素的物理屬性,如位置、大小、visible 等等,最後執行 Repaint 把算出來的結果畫到畫面上。
對使用 React 來說,React 提供了 Reconciliation 這套機制來讓我們避免處理效能的問題,而每次呼叫 render()
函式的時候,React 會去幫我們比對儲存在記憶體中的 Dom Tree 去計算出需要更新哪個節點,那這個比對的演算機制就是 Reconciliation。
樹的差異比對目前時間最佳解是 O(n3),React 則透過以下兩個假設來讓複雜度降成 O(n)。
- 兩個不同類型的 element 會產生出不同的 tree
- 開發者可以通過
key
prop 來指出哪些子 element 在不同的 render 下能保持不變
Reconciliation 最重要的概念是如果能避免直接去頻繁修改 Dom 就能增加效能,不過對於 React 的開發者來說,常常也因為撰寫上的失誤導致 render 一再的被叫用,造成雖然減少了操作 Dom 的時間卻也增加了運算量。
從 Reconciliation 的解釋中就知道,這其實是一個將直接修改 Dom 的動作們進行一個 Batch 的概念,舉例來說今天如果把某個開關用程式快速開關十次,最後其實並不會看到開關在畫面上有任何的變化出現。
在 React 的生態系中 Redux 算是常見的狀態管理套件,而操作 Redux 的 react-redux 其實也提供了 batch 的功能,目的都是希望讓 Render Tree 的操作盡可能降到最低。
渲染優化 (Rendering Performance)
在開發者工具的 More Tool 中,Rendering Tab 這個功能就可以讓我們看出當資料更新或使用者進行操作時,有哪些部分會進行重新繪製。
Rendering Tab
- Reflow: 會因為需要走完全部的 Render Tree 並逐步進行比對計算較耗資源,所以在程式撰寫上要避免觸發 Reflow
- Repaint: 相對單純,只負責重新繪製到畫面上,所以在畫面更新上的寫法盡量以觸發 Repaint 為主
舉例來說在 Hover 效果中加上了 transform: scale(2);
後,雖然這個效果只會觸發 Repaint,但如果沒有在外部容器補上 overflow: hidden;
或是限制最大寬高,在排版就蠻有可能會破版而觸發整個排版上的 Reflow 計算。
推薦 csstriggers 這個網站,如果想優化樣式的話,不妨可以到這個網站進行相關查詢。
transform 的操作本身算是無害的
腳本效能優化 (JavaScript Performance)
關於 Performance 的優話 Chrome 的開發者工具提供了 Performance、Performance Monitor、Coverage 三個方便工具,透過這兩個工具找出兇手後,就可以考慮將長時間執行的 JavaScript 做演算法上的優化或從主執行緒移動至 Web Worker 去執行,甚至是直接延後載入。
- Performance Tab: 這個 Tab 提供某段期間的錄製,透過 Call Tree 看到最花時間的 Function 在哪裏,在腳本的優化上也才比較有一個可量測可評估的方向
Performance Tab
- Performance Monitor: 則較適合邊手動測試並動態的觀察在什麼樣的操作底下會有處理器或是記憶體用量過大的情況
Performance Monitor
- Coverage Tab: 這個 Tab 可以提供從網站載入到目前的操作總共運用了多少百分比的腳本,從這裡就可以觀察我們是否需要針對 Code splitting 做優化或是尋找套件的替代方案。
Coverage Tab
喜歡這篇文章,請幫忙拍拍手喔 🤣