HTML、CSS和JavaScript,是如何變成頁面的?

按照渲染的時間順序,流水線可分爲如下幾個子階段:構建 DOM 樹、樣式計算、佈局階段、分層、繪製、分塊、光柵化和合成。

在介紹每個階段的過程中,應該重點關注以下三點內容:(輸入、處理、輸出)

1. 開始每個子階段都有其輸入的內容

2. 每個子階段有其處理過程;

3. 最終每個子階段會生成輸出內容。

(一)構建DOM樹

爲什麼要構建 DOM 樹呢?

這是因爲瀏覽器無法直接理解和使用 HTML,所以需要將 HTML 轉換爲瀏覽器能夠理解的結構——DOM 樹。

爲了更加直觀地理解 DOM 樹,可以打開 Chrome 的“開發者工具”,選擇“Console”標籤來打開控制檯,然後在控制檯裏面輸入“document”後回車,這樣你就能看到一個完整的 DOM 樹結構.

DOM 和 HTML 內容幾乎是一樣的,但是和 HTML 不同的是,DOM 是保存在內存中樹狀結構,可以通過 JavaScript 來查詢或修改其內容。

(二)樣式計算

樣式計算的目的是爲了計算出 DOM 節點中每個元素的具體樣式,這個階段大體可分爲三步來完成。

1. 把 CSS 轉換爲瀏覽器能夠理解的結構

CSS 樣式來源主要有三種:

(1)通過 link 引用的外部 CSS 文件

(2)內聯樣式

(3)內部樣式

和 HTML 文件一樣,瀏覽器也是無法直接理解這些純文本的 CSS 樣式,所以當渲染引擎接收到 CSS 文本時,會執行一個轉換操作,將 CSS 文本轉換爲瀏覽器可以理解的結構——styleSheets。

在控制檯中輸入 document.styleSheets,然後就看到樣式結構

2. 轉換樣式表中的屬性值,使其標準化

屬性標準化

3. 計算出 DOM 樹中每個節點的具體樣式

首先是 CSS 繼承。CSS 繼承就是每個 DOM 節點都包含有父節點的樣式

樣式計算過程中的第二個規則是樣式層疊。層疊是 CSS 的一個基本特徵,它是一個定義瞭如何合併來自多個源的屬性值的算法。

(三)佈局階段

現在,有 DOM 樹和 DOM 樹中元素的樣式,但這還不足以顯示頁面,因爲還不知道 DOM 元素的幾何位置信息。

那麼接下來就需要計算出 DOM 樹中可見元素的幾何位置,我們把這個計算過程叫做佈局。

Chrome 在佈局階段需要完成兩個任務:創建佈局樹和佈局計算。

爲了構建佈局樹,瀏覽器大體上完成了下面這些工作:

1. 遍歷 DOM 樹中的所有可見節點,並把這些節點加到佈局樹中;

2. 不可見的節點會被佈局樹忽略掉,如 head 標籤下面的全部內容,屬性包含 dispaly:none,這個元素就沒有被包進佈局樹

如果下載 CSS 文件阻塞了,會阻塞 DOM 樹的合成嗎?會阻塞頁面的顯示嗎?
不會阻塞DOM 樹的合成,但會阻塞頁面的顯示。
DOM 樹和CSSOM樹是並行生成的,兩個都完成後才進行佈局樹的生成,但如果期間有JS文件,那就需要等待JS文件加載並執行完成,JS也需要等待CSSOM樹生成,因爲JS可能操作DOM樹和CSSOM樹。

(四)分層

頁面中有很多複雜的效果,如一些複雜的 3D 變換、頁面滾動,或者使用 z-indexing 做 z 軸排序等,爲了更加方便地實現這些效果,渲染引擎還需要爲特定的節點生成專用的圖層,並生成一棵對應的圖層樹(LayerTree)。

要想直觀地理解什麼是圖層,可以打開 Chrome 的“開發者工具”,選擇“Layers”標籤,就可以可視化頁面的分層情況,

瀏覽器的頁面實際上被分成了很多圖層,這些圖層疊加後合成了最終的頁面。

通常情況下,並不是佈局樹的每個節點都包含一個圖層,如果一個節點沒有對應的層,那麼這個節點就從屬於父節點的圖層。

那麼需要滿足什麼條件,渲染引擎纔會爲特定的節點創建新的圖層呢?

通常滿足下面兩點中任意一點的元素就可以被提升爲單獨的一個圖層。

第一點,擁有層疊上下文屬性的元素會被提升爲單獨的一層。

明確定位屬性的元素、定義透明屬性的元素、使用 CSS 濾鏡的元素等,都擁有層疊上下文屬性。

第二點,需要剪裁(clip)的地方也會被創建爲圖層。

(五)圖層繪製

在完成圖層樹的構建之後,渲染引擎會對圖層樹中的每個圖層進行繪製,

(六)柵格化(raster)操作

通常一個頁面可能很大,但是用戶只能看到其中的一部分,我們把用戶可以看到的這個部分叫做視口(viewport)。

合成線程會按照視口附近的圖塊來優先生成位圖,實際生成位圖的操作是由柵格化來執行的。所謂柵格化,是指將圖塊轉換爲位圖。(圖片懶加載)

(七)合成和顯示

總結:

結合上圖,一個完整的渲染流程大致可總結爲如下:

渲染進程將 HTML 內容轉換爲能夠讀懂的 DOM 樹結構。

渲染引擎將 CSS 樣式錶轉化爲瀏覽器可以理解的 styleSheets,計算出 DOM 節點的樣式。

創建佈局樹,並計算元素的佈局信息。

對佈局樹進行分層,並生成分層樹。爲每個圖層生成繪製列表,並將其提交到合成線程。

合成線程將圖層分成圖塊,並在光柵化線程池中將圖塊轉換成位圖。

合成線程發送繪製圖塊命令 DrawQuad 給瀏覽器進程。

瀏覽器進程根據 DrawQuad 消息生成頁面,並顯示到顯示器上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章