發布日期:2014 年 3 月 31 日
瀏覽器必須先建構 DOM 和 CSSOM 樹狀結構,才能轉譯網頁。因此,我們需要確保盡快將 HTML 和 CSS 傳送至瀏覽器。
摘要
- 位元組 → 字元 → 符記 → 節點 → 物件模型。
- HTML 標記會轉換為文件物件模型 (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>
),以及其他尖括號內的字串。每個符記都有特殊含義和一組規則。 - Lexing:產生的符記會轉換為「物件」,定義其屬性和規則。
- DOM 建構:最後,由於 HTML 標記定義了不同標記之間的關係 (部分標記包含在其他標記中),因此建立的物件會在樹狀資料結構中連結,同時擷取原始標記中定義的父項/子項關係:HTML 物件是 body 物件的父項,body 是 paragraph 物件的父項,直到整個文件的表示法建構完成為止。
整個程序的最終輸出內容是簡易網頁的文件物件模型 (DOM),瀏覽器會使用這個模型處理網頁的所有後續作業。
瀏覽器每次處理 HTML 標記時,都會執行先前定義的所有步驟:將位元組轉換為字元、識別符記、將符記轉換為節點,以及建構 DOM 樹狀結構。整個程序可能需要一些時間,尤其是當我們需要處理大量 HTML 時。
如果您開啟 Chrome 開發人員工具,並在網頁載入時記錄時間軸,就能看到執行此步驟所需的實際時間。在前述範例中,將一段 HTML 轉換為 DOM 樹狀結構所需的時間約為 5 毫秒。如果是較大的網頁,這項程序可能需要更長的時間。在建立流暢的動畫時,如果瀏覽器必須處理大量 HTML,這可能會成為瓶頸。
DOM 樹狀結構會擷取文件標記的屬性和關係,但不會告訴我們元素在算繪時的樣貌。這就是 CSSOM 的責任。
CSS 物件模型 (CSSOM)
在瀏覽器建構基本網頁的 DOM 時,遇到文件 <head>
中參照外部 CSS 樣式表單 style.css
的 <link>
元素。系統預測需要此資源才能轉譯網頁,因此會立即調度此資源的要求,並傳回以下內容:
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 元素的子項,則會套用所有 body 樣式),然後透過套用更明確的規則遞迴式精進已計算的樣式,也就是「依序套用」規則。
為讓您更清楚瞭解這項功能,請參考先前所述的 CSSOM 樹狀結構。放置在 body 元素內的 <span>
標記中,任何包含的文字都會顯示 16 像素的字型大小,並以紅色顯示文字 - font-size
指令會從 body
向下依序連結至 span
。不過,如果 span
是段落 (p
) 標記的子項,則不會顯示其內容。
另請注意,先前所述的樹狀結構並非完整的 CSSOM 樹狀結構,只會顯示我們決定在樣式表格中覆寫的樣式。每個瀏覽器都會提供一組預設樣式,也稱為「使用者代理程式樣式」,也就是我們未提供任何樣式時所看到的樣式。我們的樣式會覆寫這些預設樣式。
如要瞭解 CSS 處理作業所需的時間,您可以在 DevTools 中記錄時間軸,然後尋找「Recalculate Style」事件:與 DOM 剖析不同,時間軸不會顯示個別的「Parse CSS」項目,而是擷取剖析和 CSSOM 樹狀結構的資訊,並在這個事件下對計算樣式進行遞迴計算。
我們的瑣碎樣式表格需要約 0.6 毫秒的處理時間,並影響頁面上的八個元素,雖然影響不大,但仍會造成額外負擔。不過,這八個元素的來源為何?CSSOM 和 DOM 是獨立的資料結構!原來是瀏覽器隱藏了重要的步驟。接下來,我們將介紹轉譯樹狀結構,將 DOM 和 CSSOM 連結在一起。