Photo by Carlos Muza on Unsplash

增進效能從了解瀏覽器開始 — 關鍵渲染路徑

Xuan Li
Walk Out 技術共筆
6 min readSep 13, 2019

--

網站畫面渲染的主要流程為,Dom -> CSSOM -> Render Tree -> Layout -> Paint,首先我們從 Server side 抓取 Html 文檔,瀏覽器解析完之後產生 Dom Tree Structure ,接著抓取 CSS 檔案,建立 CSS object model,結合兩者建立 Render Tree,在 Layout step 決定畫面的擺放接著在 Paint step 實際畫出 pixel 組織畫面

那麼最重要的 javascript 呢,若 JS 的操作會影響 DOM 的變化以及 CSS 樣式操作的話則會在 Dom -> CSSOM 的過程中循環直到JS操作完成

CRP

當我們輸入網址後,瀏覽器便會送出 Request 至 Server side,Server 的回覆便是對應的 html 文檔,那麼瀏覽器是怎麼根據 html tag 去決定產生什麼畫面的呢?

瀏覽器有定義好的步驟去解析 Html 並產生對應的 DOM structure,第一瀏覽器的 tokenizer 會根據 html tag 轉編成 token tag (可見下圖)與此同時,每個 token tag 也會另一個 process 轉變成 node object,而最後的token結束後我們也就得到一個 node object 的樹狀結構,也就是 DOM

Tokenizer convert html into token tag
token tag to DOM tree

此步驟有一個重點可以優化網站速率,也就是 DOM 的建構過程是逐步的,所以我們可以選擇將固定的畫面例如 header 的部分先 render 出來優化使用者體驗,同時也不必讓 header 需要浪費時間等待網站實際內容的回傳後才一起描繪畫面.

再來提到 CSS 的解析過程,由先前的圖可以知道瀏覽器解析完HTML後接著會便是我們的造型師 — CSS,同樣瀏覽器會對 css 檔案做解析並建立類似於 DOM tree 的 CSSOM,,至於實際上解析的細節規則大家有興趣可以自己上網查詢,在這只做簡單介紹,如下圖所示同樣會根據解析規則建立 node,並根據 parent node 的關係去連結.

CSS to CSSOM flow

值得注意的一個基本觀念就是,CSS 是可以覆寫定義樣式的,也因此不同於 html 可以選擇先 render partial content,我們無法只先引用局部的樣式,因此 CSS 是為 render blocking,也就是說,在瀏覽器確認處理好所有 css 相關程序之後才會開始 Render 頁面

redefine style example

有了 content(HTML) & style(CSS),接著就是進入到 Render Tree 的部分了.瀏覽器接著會比對 DOM & CSSOM 兩個樹狀結構進而在分析出一個 Render Tree 的結構.由下圖可以看到大概解析後的樣子,注意 display: none 是完全不存在 Render Tree,可以看到相對應的 Dom node 並不會被分析進入 Render Tree 的結構中,然而簡而言之,Render Tree 只包含顯示在頁面上的節點

溫馨提醒 visibility: hidden 還是會轉譯成 Render Tree node 的一部份,此屬性實際上是提供了空白區塊

Dom + CSSOM = Render Tree

有了各個節點的樣式與內容後,接著進入版面配置的部分,版面配置主要是計劃在節點各個裝置上所需的大小以及準確位置,而此步驟可以透過 meta tag 對 viewport 的設定而有所相對應的計算方式,相信大家都對下面這行不陌生吧?

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

而版面配置計算完成後實際上會輸出一個 box model,相信大家也不陌生這東西,Box Model 紀錄了每個節點的準確位置和大小,而這些數據則會透繪製的步驟實際轉化成頁面上的 pixel,詳盡行為都可以透過DevTool觀察到

上圖可以發現 Layout 的計算不只一次,因為每次因為樣式更換或者 DOM 結構改變以及裝置的變化 Ex: 手機橫向以及垂直、頁面放大縮小,都會重新進行版面配置計算,這也是為什麼 DOM 的操作成本大的原因之一

綜合以上我們針對瀏覽器的渲染行為簡單劃個小重點

  1. 處理 HTML ,產生 DOM 樹狀結構。
  2. 處理 CSS ,產生 CSSOM 樹狀結構。
  3. DOM + CSSOM = Render Tree。
  4. 針對 Render Tree 進行版面配置,計算每個節點的大小以及位置。
  5. 在螢幕上繪製各個節點。

如果修改了 DOM 或 CSSOM,以上的行為就會無限循環,以確定需要在螢幕上重新呈現的像素,因此優化整個渲染行為就是想方設法的簡短上述行為所花費的時間,時間越短就能越快呈現頁面給使用者以提供更好的使用者體驗,在此強烈呼籲大家可以找自己常逛的網站試著用 DevTool Performance 去看一下這些網站在此上述行為上所消費的時間,並試著想想可以從哪點去改進.

以上就是一個小小學習筆記,如有錯誤或者建議再請大家留言,感謝閱讀

Reference — https://www.udacity.com/course/website-performance-optimization--ud884

--

--

Xuan Li
Walk Out 技術共筆

來自1994的前端菜鳥,剛從紐西蘭打工度假回來。