瀏覽器必須先建構 DOM 和 CSSOM 樹狀結構,才能轉譯網頁。因此,我們必須盡快將 HTML 和 CSS 提供給瀏覽器。
摘要
- 位元組 → 字元 → 符記 → 節點 → 物件模型。
- HTML 標記可轉換為 Document 物件模型 (DOM),CSS 標記則會轉換成 CSS 物件模型 (CSSOM)。
- DOM 和 CSSOM 是獨立的資料結構。
- Chrome 開發人員工具的效能面板可讓我們擷取及檢查 DOM 和 CSSOM 的建構和處理費用。
文件物件模型 (DOM)
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link href="style.css" rel="stylesheet" />
<title>Critical Path</title>
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg" /></div>
</body>
</html>
首先,我們從最簡單的情況開始:一個包含一些文字和一張圖片的純 HTML 網頁。瀏覽器如何處理這個網頁?
- 轉換:瀏覽器從磁碟或網路讀取 HTML 的原始位元組,然後根據指定的檔案編碼 (例如 UTF-8),將其轉換為個別字元。
- 權杖化:瀏覽器會將字元字串轉換為不同的符記,以符合 W3C HTML5 標準指定的內容 (例如「<html>」、「<body>」及角括號內的其他字串)。每個符記都有特殊意義和一組規則。
- 放出:發出的符記會轉換為「物件」,並定義其屬性和規則。
- DOM 結構:最後,由於 HTML 標記定義了不同標記 (某些標記包含在其他標記中) 之間的關係,因此建立的物件會在樹狀資料結構中連結,而此結構也會擷取原始標記中定義的父項與子項關係:HTML 物件是 body 物件的父項,body 是 paragraph 物件的父項,依此類推。
整個程序的最終結果是簡單網頁的 Document 物件模型 (DOM),瀏覽器會使用該模型進行頁面後續處理。
每次瀏覽器處理 HTML 標記時,都會進行上述所有步驟:將位元組轉換為字元、識別符記、將符記轉換為節點,以及建構 DOM 樹狀結構。這整個程序可能需要一段時間才能完成,尤其是處理大量 HTML 時。
如果您開啟 Chrome 開發人員工具,並在網頁載入時記錄時間軸,就可以看到執行這個步驟實際所需的時間。在上述範例中,將一段 HTML 區塊轉換為 DOM 樹狀結構約需 5 毫秒。如果頁面較大,這個程序可能需要花費許多時間。建立流暢動畫時,如果瀏覽器必須處理大量 HTML,很容易就會變成瓶頸。
DOM 樹狀結構會擷取文件標記的屬性和關係,但不會告訴我們元素轉譯後的樣子。這正是 CSSOM 的責任。
CSS 物件模型 (CSSOM)
瀏覽器建構簡易網頁的 DOM 時,在文件的 head 區段遇到一個連結標記,參照外部 CSS 樣式表:style.css
。系統預期需要這項資源才能轉譯網頁,會立即分派對這項資源的要求,而要求會傳回以下內容:
body {
font-size: 16px;
}
p {
font-weight: bold;
}
span {
color: red;
}
p span {
display: none;
}
img {
float: right;
}
我們可直接在 HTML 標記 (內嵌) 中宣告樣式,但如果讓 CSS 與 HTML 不同,我們將分別處理內容和設計:設計人員可以處理 CSS、開發人員專注在 HTML 上等等。
與 HTML 一樣,我們需要將收到的 CSS 規則轉換為瀏覽器可以理解及運作的內容。因此,我們重複執行 HTML 程序 但對於 CSS 而非 HTML:
CSS 位元組會轉換為字元,然後轉換為符記和節點,最後又會連結到稱為「CSS 物件模型」(CSSOM) 的樹狀結構:
CSSOM 為什麼採用樹狀結構?計算網頁上任何物件的最終樣式組合時,瀏覽器會從適用於該節點的最通用規則開始 (例如,如果這是 body 元素的子項,就會套用所有主體樣式),然後套用更具體的規則,以遞迴方式調整運算樣式;也就是說,規則會「向下傳遞」。
為了更具體地說明,不妨考慮上方的 CSSOM 樹狀結構。<span>
標記中包含的所有文字,如果放在 body 元素中、字型大小為 16 像素,且含有紅色文字,則 font-size
指令會從 body
向下傳遞至 span
。不過,如果 span
標記是段落 (p
) 標記的子項,就不會顯示其內容。
此外,請注意,上述樹狀結構並非完整的 CSSOM 樹狀結構,只會顯示我們決定在樣式表中覆寫的樣式。每個瀏覽器都會提供一組預設樣式 (又稱為「使用者代理程式樣式」),也就是不提供任何自有樣式時會看到的樣式,而我們的樣式只是覆寫這些預設值。
如要確認 CSS 處理作業需要花費多久時間,您可以在開發人員工具中記錄時間軸,並尋找「重新計算樣式」事件:與 DOM 剖析不同,時間軸不會顯示個別的「Parse CSS」項目,而是擷取剖析和 CSSOM 樹狀結構結構,以及這個事件下的運算樣式遞迴計算。
處理流程需要約 0.6 毫秒,且會影響網頁上的八個元素,操作少之多,只是一次,不會造成任何影響。不過,八個元素是從哪裡來的?CSSOM 和 DOM 是獨立的資料結構!原來,瀏覽器隱藏了一個重要的步驟。接下來,我們來談談連結 DOM 與 CSSOM 的轉譯樹狀結構。