Sitemap
Chiao

Chiao

瀏覽器渲染機制

探討瀏覽器從讀取檔案到繪製畫面的過程

11 min readFeb 10, 2023

--

前導知識:瀏覽器架構的演進

瀏覽器的架構演進是由「單進程時代」走到「多進程時代」的歷程,原先「單進程時代」讓網頁瀏覽器具有三大缺點:不穩定、不順暢、不安全,而自 2008 年 Chrome 發布多進程的瀏覽器架構後,讓一個瀏覽器可獨立運作多個進程,其中至少包含瀏覽器主進程、渲染進程、網路進程、GPU 進程共四個進程,以及其他插件進程等。

現今瀏覽器朝向「服務導向架構」邁進,將每個進程視為獨立的服務,可彈性地整合多個服務至同個進程,如將瀏覽器主進程整合網路模組、profile 模組、UI模組等,或是同時執行多個進程(如下圖)。

Press enter or click to view image in full size
參考來源:宏观视角下的浏览器:仅仅打开了1个页面,为什么有4个进程?

以上略述進入本篇主題的先備知識,瞭解瀏覽器架構發展的始末後,本篇主要細談瀏覽器渲染畫面的原理,瀏覽器渲染機制主要由渲染進程、GPU 進程、主瀏覽器進程三者各司其職負責渲染出網頁畫面,透過認識瀏覽器渲染畫面的運作,可讓前端開發時在 CSS 和 DOM 操作過程中,避免寫出耗廢效能的程式碼和網頁優化的小技巧,若想直接瞭解開發上的優化技巧,可參見「前端開發的關鍵優化技巧」一文。

瀏覽器渲染畫面的原理

瀏覽器渲染畫面的過程就像是一座工廠,有不同的廠區負責各自的職責,而每個廠區有自己的生產線,按照流水線依序產出該區的產物,而產線末端會有一個負責組裝半成品的專區,最終得以完成一個產品。

Press enter or click to view image in full size

一、廠區基本簡介

前述提及瀏覽器渲染機制主要由渲染進程、GPU 進程、主瀏覽器進程三者各司其職負責渲染出網頁畫面,以下簡述瀏覽器渲染機制執行過程:

A廠區-渲染進程:

渲染進程包含「主線程」和「合成線程」以下兩種生產線:

a. 生產線-主線程

本生產線執行多個子階段:

子階段:解析 HTML &CSS ➡ Layout ➡ Layer ➡ Paint(繪製列表)

  1. 解析 HTML &CSS 階段:負責將 HTML、CSS、JS 的程式碼轉換成瀏覽器讀得懂的形式,如將 HTML 解析成 DOM tree 又或是將 CSS 解析成 CSSOM。
  2. Layout 階段:負責篩選出顯示於畫面的元素,將元素安排在畫面中對應的位置與大小。
  3. Layer 階段:針對這些元素歸納在不同圖層中,產生分層的上下疊層關係。
  4. Paint 階段:針對各圖層擬定繪製執行指令的列表。

b. 生產線-合成線程

負責將畫面切分成多個圖磚(tile),並執行網格化(將向量轉成網格的過程),此生產線負責將結果提交給其他產區。

  1. 提交B廠區- GPU 進程:將網格化結果提交給 GPU 進程。
  2. 提交C廠區-主瀏覽器進程:產出 Drawquad 指令提交給主瀏覽器進程進行處理。

B廠區-GPU 進程:

GPU 是繪圖處理器,負責將加速網格化的過程,最終產生點陣圖並將資料保存在 GPU 中。

C廠區-主瀏覽器進程:

當取得 Drawquad 指令後,根據指令繪製頁面內容,負責將多個圖層合併,顯示最終的網頁畫面。

二、詳談廠區功能

前述提到瀏覽器選染網頁畫面的過程,就像是一條工廠的生產線,由上游經過不同子階段並串接至下游,最終產出成品的過程,而這條生產線稱之為「渲染流水線」,以下讓我們詳細述說整個流水線的生產過程吧!

A廠區-渲染進程:

a. 生產線-主線程

  1. 解析 HTML & CSS 階段

由於瀏覽器本身是無法直接讀懂 HTML、CSS 的內容,因此當瀏覽器收到來自伺服器端所回應的 HTML、CSS 檔案時,需要有一個負責翻譯的角色,將檔案能解析成為瀏覽器能讀取的格式。

以 HTML 來說,每個 HTML 元素會被解析成 「DOM tree」,將元素對應轉換成物件模型,並且以 document 當作根節點,所形成的樹狀結構。

以 CSS 來說,由於有些樣式單位是相對值或是名稱,如 rem、%、red 、blod 等,這會讓瀏覽器無法直接讀取,因此會經由樣式計算先將樣式換算轉為絕對單位,如 px、rgb(255,0,0)等,最後也須將 CSS 轉換成 stylesheet 格式,並且以 CSSOM 表示。

最後 CSSOM 內樣式會依序對應到 「DOM tree」 內的每個元素,有關 DOM 的說明可參見「簡介瀏覽器環境」一文。

2. Layout 階段

此階段稱為「佈局」就是負責畫面中分配位置的功能,「佈局」主要分為兩個階段:

第一階段:篩選出可顯示於畫面的中的元素,並產生「佈局樹」,而不會出現於畫面的元素可能是樣式設定 display: none、或是原本 DOM 中的 head 標籤。
第二階段:負責定位,主要透過樣式中的 float 或 position 的設定,將每個 DOM 佈置在畫面中相對應的位置。

Get Chiao’s stories in your inbox

Join Medium for free to get updates from this writer.

3. Layer 階段

在 Layer 階段前網頁畫面仍是二維平面的配置,而實際上網頁可展現許多三維立體的效果,如旋轉、上下堆疊關係、立體等,這些效果主要來自於 Layer 階段,簡而言之, Layer 階段在 DOM 元素中創造上下文堆疊,使其具有三維空間。

上下文疊層(又可以直接想像成圖層)主要沿著一條虛擬的 Z 軸進行排列分層,上下文疊層的關係影響畫面與使用者間的距離。在判斷 DOM 元素的上下文堆疊具有特定條件做判定,瀏覽器首先會遍歷 DOM tree 中的所有 DOM 元素,依據元素的樣式屬性,決定是否會獨立成疊層,最終會產出「分層樹」。

參考來源:MDN 上下文堆疊

DOM 元素上下層堆疊的判斷原則,當樣式中符合下列條件:

  1. 定位屬性:僅 position 為 absolute 或 relative 。
  2. 容器:display 是 flex 或 grid。
  3. 透明度:設定 opacity 小於1。
  4. 其他任一不為 none 的屬性:transform、filter、clip-path等。
  5. 內文剪裁:當內文超過區塊尺寸時,文字會自動被剪裁符合該尺寸,此時,文字會自動形成一層,而產生的 scroll bar 也會自行成一層。
Press enter or click to view image in full size

透過樣式的 z-index 決定圖層的優先順序,具有下列使用關聯和原則:

  1. 疊層間的層級關係:具有父子(層包含在層內)和兄弟姊妹(層和層平行)。
  2. z-index 疊層處理:僅考慮父子層級關係,兄弟姊妹層級關係彼此獨立。
  3. 疊層自包含:元素僅有符合前述樣式條件才會自形一層,而其他不符合條件的元素則會與其父疊層同化。

4. Paint 階段

Paint 階段會根據「分層樹」中的每一層,依序產生繪製列表,而繪製列表是由許多繪製指令構成,繪製指令包含繪製項目(圖片、文字、圖型、路線等),其中也會包含座標的資訊,在這階段主線程會依據擬定出每一層的繪製列表,接著,準備提交給合成線程透過 GPU (圖型處理器)執行繪製。

Press enter or click to view image in full size
參考來源:渲染流程:HTML、CSS和JavaScript是如何变成页面的?

b. 生產線-合成線程 &B廠區-GPU 進程

當Paint 階段由主線程提交繪製列表給合成線程後,會進行「網格化」的過程,網格化即是將原本向量轉換成網格的點陣圖形式。

而在頁面中執行網格化具有特定的優先次序,以整個頁面來說,會將頁面切分成多個圖磚(tile),而螢幕中可見區域稱為視口(viewport),網格化會優先將位於視口的圖磚進行網格化,而一個圖磚的網格化會由多個網格線程執行,也可稱作為「網格化線程池」,最後透過 GPU 負責生成點陣圖,並存取在 GPU 中。

參考來源:渲染流程:HTML、CSS和JavaScript是如何变成页面的?

C廠區-主瀏覽器進程(compositing)

合成線程會生成一個繪製圖磚的指令「DrawQuad」,並將指令提交給瀏覽器線程,瀏覽器線程根據指令,負責合併多個圖層,並將合併結果顯示於畫面中。

參考來源:渲染流程:HTML、CSS和JavaScript是如何变成页面的?

總結

瀏覽器的渲染過程就像是一個工廠的運作模式,透過渲染進程、GPU 進程、主瀏覽器進程分別按照各自的生產線完成網頁的畫面,主要的重點步驟:

  1. 解析來自伺服器端的 HTML 和 CSS 檔案,產生 DOM 和 CSSOM,而CSSOM 會合併到每個 DOM tree。
  2. Layout 產生「佈局樹」,遍歷所有的 DOM tree 篩選可顯示於畫面的 DOM 元素,並將元素配置到畫面的位置中。
  3. Layer 產生「分層樹」,將二維空間轉成三維空間,產生上下文堆疊。
  4. Paint 產生繪製列表。
  5. 合成線程提交網格化的疊層,在交由 GPU 進程處理。
  6. Compositing 由主瀏覽器進程負責將不同的疊層合併,最終顯示於畫面中。

以上是瀏覽器渲染的主要步驟,而每當開發人員開發頁面時,會對於網頁樣式進行調整,這時候又涉及「Repaint」和「Reflow」,而「Repaint」是有關 visbility 的調整,如透明度、顏色、背景色、可見等,會導致重新回到瀏覽器渲染的 Paint 步驟;而「Reflow」則是有關佈局的調整,如寬高度、位置等,導致重新回到瀏覽器渲染的 Layout 步驟,而開發過程中期待最小化「Repaint」和「Reflow」來減少資源消耗,因此可透過一些開發技巧上來優化網頁的渲染,下一篇詳談開發技巧和檢視網頁表現度的方法!(請參見「前端開發的關鍵優化技巧」)

參考來源:

--

--