JS 原力覺醒 Day25 - CRP : 關鍵渲染路徑

當使用者進入頁面、瀏覽器收到請求並回傳前端相關檔案後,到最後使用者看到的畫面呈現之前,還有很多步驟會被執行,這一連串步驟的總和就稱為 Critical Rendering Path ( 中譯:關鍵渲染路徑),了解關鍵渲染路徑,在網站前端頁面需要做效能優化時,就可以比較容易知道,要從哪裡下手。
https://ithelp.ithome.com.tw/upload/images/20190916/20106580lJIWdcHc2t.png

關鍵渲染路徑(以下簡稱 CRP ) 大致上會執行以下六個步驟:

  1. 建構 DOM Tree
  2. 建構 CSSOM Tree
  3. 執行 JavaScript
  4. 創造渲染樹
  5. 產生畫面佈局
  6. 繪製、產生畫面

下面就讓我們一個步驟一個步驟詳細來看:

Step1. 建構 DOM Tree

前一章節有講到網頁的 DOM 是根據 HTML 內容而來,這個轉換的過程有點像這個系列一開頭我們討論 JS 語法解析那段,瀏覽器會根據 HTML Tag 將內容轉為一個一個 Token (標記)

https://ithelp.ithome.com.tw/upload/images/20191010/201065802PnTTlOshi.jpg

之後會根據這些 Token 將對應的標籤轉換成節點,之後根據 Token 的前後關係產生出 DOM Tree 。

https://ithelp.ithome.com.tw/upload/images/20191010/20106580peW9V1tTe4.jpg

Step2. 建構 CSSOM Tree

CSSOM ( CSS Object Model ) 是代表跟 DOM 元素對應樣式的物件。他的表現形式跟 DOM 很像,只是 CSSOM 是依附著每個節點,各個節點都會有對應的樣式 ( Style ),所以基本上 CSSOM Tree 跟 DOM Tree 長的會很像。

https://ithelp.ithome.com.tw/upload/images/20191010/20106580iAbwkUacyT.jpg

這邊要注意的是,CSS 在頁面載入行為裡,是屬於鎖定渲染的資源( Render Blocking Resource ),意思是,在頁面仔入時,只要還沒有拿到所有的 CSS 檔案並成功載入,那瀏覽器就會等到完成載入為止,這意味著,每個網頁上的 CSS 檔案,都會拖到載入速度。

除了 Render Blocking ,也有人說 CSS 是 「Script Blocking 」,因為在瀏覽器載入所有的 CSS 檔案之後,瀏覽器才會進入的我們的下一步「執行 JS」。 在產生 CSSOM 時,越多層的選擇器,在元素與樣式的匹配上會需要更多時間來進行。以下面這兩個 CSS 類別為例:

A : p {  color:red; } 

B : div h1 { font-size:22px;}

第二種 B 情況的 CSS 會需要更多時間來做匹配,首先瀏覽器會先找到頁面上所有的 h1 元素,而後在看這個元素的父類別是不是一個 div 元素 ,因此瀏覽器在匹配樣式時其實是以「從右邊到左邊」的順序來進行的,所以現在你就了解,如果你有加速前端渲染速度的請求,就要減少 CSS 選擇器層級的長度,在這方面,BEM 的 CSS 命名撰寫風格就把層級關係透過命名的方式來表達,同時也大幅度的減少選擇器的少用次數,建議對 CSS 有興趣鑽研的人一定要看一下。

類似的命名風格或規範,除了 BEM 之外還有 OOCSS 跟 SMACSS ,這些規範都是透過一些原則,來達到最大程度的減少重複,除了好維護之外,其實也能提升畫面渲染的效率,這也是為什麼這些規範常常被資深前端人員提起、並視為圭臬的原因。

Step3. 執行 JS

JS 則是鎖定轉譯,在 JS 執行完之前,瀏覽器都不會繼續做 HTML 文件的轉譯跟建構。當瀏覽器轉譯時碰到 <script> ,他會停下來等到 JS 執行完成之後才會再往下。這也是為什麼我們常常說要把 <script> 標籤放到整個網頁最後面的原因。

Step4. 創造渲染樹

渲染樹 (Rendering Tree) 其實就是 DOM 搭配 CSSOM 的結果,在用白話一點的方式來說,就是「最後會被渲染在畫面上」的結構樹,所以如果 CSS 樣式導致某個 Node 沒辦法顯示,( 如display:none ),那麼他就不會出現在渲染樹上。

Step.5 產生畫面編排 ( Layout )

我們已經取得代表元素層級關係的 DOM 樹結構,也匹配了個元素對應的樣式,最終搭配兩者產生出了渲染樹,現在我們離最後產生可視畫面的階段已經不遠了,但是還差一個步驟,我們還必須弄清楚所有元素的實際位置,以及元素該如何呈現,那就是產生畫面編排 ( Layout ) 的步驟。

Layout 產生的方式,會跟 meta tag 裡面的 viewpoint 屬性有很大的關係:

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

viewpointmeta tag 用來告訴瀏覽器,頁面要怎麼縮放,還有維度,就是指畫面像素(瀏覽器畫面)跟螢幕像素(硬體)的比例,content 之中,width 用來設定瀏覽器畫面寬度是多少,把他設定成 device-width 的話就是在告訴瀏覽器,畫面顯示的螢幕寬度要跟硬體裝置相同(手機、電腦),如果沒給 width 值的話,瀏覽器就會使用預設的 980px 來當作預設的畫面顯示寬度。這個屬性在 HTML5 後出現,常用在 RWD 的設計實作之中。 initial-scale=1.0 是指預設的縮放程度,最常見的值也是預設值,就是 1

Step6. 繪製、產生畫面

到最後一個步驟,瀏覽器進入到了繪製階段,前面提到一連串很抽象的設定跟結構,終於可以被轉換成一個個像素,繪製階段所花的時間會跟 DOM 結構樹 與 CSSOM 樹的大小、規模有關,越複雜的結構或是樣式就會需要更多時間,應該不難理解。

從開發者工具看渲染順序

我們透過瀏覽器的檢查工具,也能看出上面講的 CRP 六個步驟,是不是真的依照順序進行,以 Chrome 為例子,打開開發者工具,並切換到 Performance 之後,按下錄影,重新整理之後結束錄影,就能夠看到這段時間內瀏覽器是怎麼產生畫面的:

https://ithelp.ithome.com.tw/upload/images/20191010/20106580UtQhk3zM67.jpg

對應前面步驟說明:

1、2: 拉取資源並解析 DOM 樹

  1. 為 index.css 解析 CSSOM 樹

  2. 執行 JavaScript 檔案 ( index.js )

  3. 根據 viewpoint 的 meta tag 產生layout

  4. 繪製螢幕

參考資源

Google 在 Udacity 的教學真的講的蠻仔細的,搭配圖文也能更讓學習者一目瞭然:

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×