什麼是關鍵渲染路徑 (critical rendering path)?

2024年9月7日

💎 加入 E+ 成長計畫 如果你喜歡我們的內容,歡迎加入 E+,獲得更多深入的軟體前後端內容

身為前端工程師,關鍵渲染路徑 (critical rendering path) 是在開發時,經常需要打交道的一條路徑,也是業界做效能優化分析時,經常會提到的一條路徑。

所謂的關鍵渲染路徑,是瀏覽器從下載 HTML、CSS、JavaScript 等文件,到把這些文件轉換成使用者可以看、可以互動的網頁的過程。

什麼是關鍵渲染路徑?

所謂的關鍵渲染路徑,是瀏覽器從下載 HTML、CSS、JavaScript 等文件,到把這些文件轉換成使用者可以看、可以互動的網頁的路徑。

具體來說,這條路徑包含以下不同的步驟:

  • 下載與解析 HTML,建構出 DOM
  • 下載與解析 CSS,建構出 CSSOM
  • 下載與解析 JavaScript,如有任何 JavaScript 會動到 DOM 或 CSSOM,則會執行 JavaScript 去改變 DOM 與 CSSOM
  • 根據 DOM 與 CSSOM 建構渲染樹 (render tree)
  • 計算樣式與佈局 (layout)
  • 在記憶體中繪製 (paint) 像素
  • 將不同的圖層合成 (composite)
  • 實際將像素繪製到畫面上

如果要視覺化理解上面的路徑,會是像下面這樣

  HTML            CSS
    ↓              ↓
   DOM           CSSOM
    ↓              ↓
        ↘     ↙
      JavaScript

     Render Tree

       Style

       Layout

       Paint

     Composite

      Display

為什麼要對這個路徑有所掌握?

在理解完關鍵渲染路徑的基本介紹,這時你可能會問,為什麼身為前端開發者,我們會需要理解這個路徑? 有什麼好處?

身為前端工程師,效能優化是工作與面試時,經常需要面對到的議題。當談到前端效能優化,有非常多不同的切入點可以討論。

然而,如果想要有架構一點地討論前端的效能優化,最推薦的方法之一,即是從路徑的角度切入展開來討論,這樣就能把在路徑中的每一個點,分別拉出來談可以如何優化。

所以對關鍵渲染路徑有所掌握,將能夠讓你更能有架構地分析前端、優化前端地效能。

DOM 與 CSSOM 的角色

關鍵渲染路徑是從建構 DOM 與 CSSOM 開始,可以把 DOM 與 CSSOM 理解成 API,是透過轉換成這個標準化的形式,讓 JavaScript 可以去操作 DOM 與 CSSOM 上的元素。

以 DOM 來說,當 JavaScript 要去修改某個元素,或加事件監要去修改某個元素,都需要一個標準,讓外部可以去操作與修改 HTML,而 DOM 即是提供這個標準,讓 JavaScript 能夠去操作與修改 HTML。

因此,HTML 被解析後會建構 DOM,而 JavaScript 透過修改 DOM 來去改內容。同樣地,瀏覽器下載完、解析完 CSS 後,會生成 CSSOM,而 CSSOM 也可以理解成一個 API,讓 JavaScript 能夠去修改樣式。

在初步理解完 DOM 與 CSSOM 後,我們就能進一步來討論,可以如何優化這兩個要件。

HTML 優化

要優化下載與解析 HTML,到 DOM 的建構這段,可以有幾個思考點:

1. 讓 HTML 變小

如果 HTML 文件越大,就要花越多時間下載與解析。因此,可以去思考使用者進到頁面中,有什麼部分是真正需要出現在首次渲染的畫面中,只放真正需要的內容,讓 HTML 盡可能變小,下載與解析起來就會快。

2. 如何讓 DOM 盡可能最小化

常見的方式包含做分頁 (pagination),比起一次就呈現很多頁,導致要處理的元素很多,拆成多個頁面,在需要時再加載,這樣的效能會比較好。與此同時,可以透過虛擬化 (virtualization) 來讓 DOM 變小。

先前有一個測試 (連結),同樣是 10 萬行的 DOM,渲染起來約要 242 毫秒,但如果用虛擬化的方式渲染,只需約 2.4 毫秒,這有相當大的差別。

3. HTML 用串流的方式傳

因為 HTML 是可以被逐步解析 (incrementally parsed),所以可以不用一次傳一整份,傳完才解析,而是可以切成不同的小部分,然後串流的方式傳到客戶端,這樣瀏覽器一接受到就可以直接開始解析,不用等整個 HTML 都下載完開始解析。

CSS 優化

接著來談 CSS 部分的優化。在談之前,有一個必須先談的預設,就是瀏覽器會預設把 CSS 視為阻擋渲染的存在。意思是,當瀏覽器在解析 HTML 時,遇到會阻擋渲染的 CSS,就會停下來先處理 CSS,然後再回頭解析 HTML。

之所以會阻擋渲染,是因為如果不阻擋,在 CSSOM 建構完後,又有新的樣式變更,會讓畫面樣式跳來跳去,這樣使用體驗很差。為了有良好的使用體驗,在瀏覽器端才會設計成必須要等 CSSOM 建構完成才渲染。

在有了以上的觀念後,可以透過以下手段來優化:

1. 把 CSS 放在文件最上方

CSS 要盡量放在最上方,這樣才可以盡早下載、解析,然後形成 CSSOM;這段儘早完成就能儘早結束對渲染的影響。

2. 讓 CSS 文件盡可能小

最小化 CSS (用 minimizer),以及把首屏不用的 CSS 移除掉,後面再加載就好。這麼做就能及早讓 CSS 被處理完,不會持續阻擋渲染。

3. 修改對首屏不重要的 CSS 的預設行為

前面瀏覽器預設 CSS 會阻擋渲染,但這點不是不能改變的。把對不重要的 CSS 改成不會阻擋渲染,也能讓渲染更快完成。這點詳細推薦 《The Simplest Way to Load CSS Asynchronously》 一文。

閱讀更多

如果你對關鍵渲染路徑這個主題感興趣,我們在 E+ 有更完整講解的版本,包含討論為什麼這條路徑有「關鍵」稱呼、JavaScript 在這條路徑上扮演的角色、如何優化 JavaScript 對這條路徑的影響、佈局與繪製階段的討論與優化。有興趣的讀者,歡迎加入 E+ 成長計畫。

本文為 E+ 成長計畫的深度內容,截取段落開放免費閱讀。歡迎加入 E+ 成長計畫閱讀完整版本 (點此了解 E+ 的詳細介紹)

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們