DOM render
嗯,之前看到這篇文章,一直知識這塊大概只需要點擊收藏,大概就是高近視的老師閱券,嗯,學會了 XD
DOM performance
Web Performance Optimization
Rendering Performance
一樣先來個肌肉訓練,進入正題好了,先說瀏覽器透過網址向 server 取得 response 內容 (HTML),並且開始建構 DOM tree 的流程。
有些還沒有看完,之後再回頭補完好了。
解析 HTML
- Browser 向 server 取得 html
- 解析 HTML 成 tokens, 如 tagName, Attributes
- tokens 再轉成 nodes
- nodes 再轉成 DOM tree
- CSSOM 從 css rules 建構出來
解析 HTML 過程裡,有一些渲染阻塞的問題,而在阻塞過程都以白屏顯示:
DOM tree 是逐步解析 HTML,且逐部增加的,不是一次性的加入
解析過程若遇到 <link>
token,還是 <script>
token,這都會阻塞 DOM tree 的建構
因為這些檔案,可能牽涉 DOM render 資訊,如 SPA,JS 可以 render DOM / 調整 style
CSS 檔案則可以再產生出新的 CSSOM 節點
另外,CSSOM 無法被建構成一個完整的 tree,因為並非每一個 DOM 都有 styles 屬性,想靠 styles 建立出完整的 tree 是不可能的,因此它只能依賴著 DOM tree 去附加 styles 屬性
Render tree - 根據 CSSOM 及 DOM tree 合併
- 當所有 JS / CSS 及 HTML 都已完成處理,CSSOM + DOM tree 會合併成一棵 Render tree
- 這包含了可視元件及其 styles 的運算
- 不可視的元件會被 prune 掉,以節省資源,如 meta / link / head 這種
- Reflow 階段會去計算所有可視節點的位置和大小
- 決定多層頁面 layer (z-index / fixed / absolute )
Paint
- 當 render tree 已經將所有 layout style (位置/大小/圖層)相關都已處理完畢,因此就只需要輸出到畫面
JS 執行 & 渲染 Paint 都在主執行緒執行,若互相搶取資源就會造成畫面卡頓。
效能改善的方案
減少 repaints & reflow 觸發次數
- 批量修改 styles
- 批量新增 / 修改 / 刪除 DOM
- 使用 visibility: hidden/visible 取代 display: none
- 使用 transform 取代 top / left / bottom / right
- preload locally font file (字型會影響 layout 造成 reflow)
- image 可事先定義 layout 大小,不會載入圖片後造成 reflow
- 建立圖層 z-index / fixed / absolute
- viewport 大小改變
- :hover, :before, :after
阻塞資源
- 減少不必要的資源請求
- 合併多個小資源的請求
- 只載入必要的資源 (使用 js tree shaking & 移除未用的 css)
- 最小化資源 (使用 server gzip & 壓縮 js / css)
- 廣告 tracking 非網站主要運行邏輯,可延後載入,使用 defer & async
- 縮小 font 檔案
<script>
放在 <body>
下方,為了防止因阻塞而頁面 render 不全
- async: 異步下載完後執行,HTML parsing 可能被阻塞,僅對外部資源有效
- 跟 DOM 無關的 js,可能先於 DOMContentLoaded 也可能後於 DOMContentLoaded
- defer: 先下載不馬上執行,等 HTML parsing 完後,才開始依序執行,僅對外部資源有效
- 依賴 DOM 的 js,先於 DOMContentLoaded
<link rel="prefetch | preload | dns-prefetch | preconnect | prerender">
- prefetch: 預先載入,但不先執行
- prerender: 預先載入,並執行
- preload: 優先載入的資源,通常為主要資源加載
- preconnect: 預先建立 tcp / tls 連接
- dns-prefetch: 預先查詢 dns
— 2022年12月4日