建構物件模型

Ilya Grigorik
Ilya Grigorik

發布日期: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 網頁,其中包含一些文字和單一圖片。瀏覽器如何處理這個網頁?

DOM 建構程序

  1. 轉換:瀏覽器會從磁碟或網路讀取 HTML 的原始位元組,然後根據檔案的指定編碼 (例如 UTF-8) 將其轉換為個別字元。
  2. 符記化:瀏覽器會將字元字串轉換為不同的符記 (如 W3C HTML5 標準所指定,例如 <html><body>) 和其他角括號內的字串。每個符記都有特殊含義和一組規則。
  3. Lexing:產生的符記會轉換為「物件」,定義其屬性和規則。
  4. DOM 建構:最後,由於 HTML 標記定義了不同標記之間的關係 (部分標記包含在其他標記中),因此建立的物件會在樹狀資料結構中連結,同時擷取原始標記中定義的父項/子項關係:HTML 物件是 body 物件的父項,bodyparagraph 物件的父項,直到整個文件的表示法建構完成為止。

DOM 樹狀結構

這整套程序的最終輸出結果是文件物件模型 (DOM) 也就是瀏覽器用來進一步處理 頁面。

瀏覽器每次處理 HTML 標記時,都會執行先前定義的所有步驟:將位元組轉換為字元、識別符記、將符記轉換為節點,以及建構 DOM 樹狀結構。整個程序可能需要一些時間 特別是當要處理大量 HTML 時

在開發人員工具中追蹤 DOM 建構作業

如果您在載入頁面時開啟 Chrome 開發人員工具,並錄製時間軸, 您會看到執行這個步驟的實際時間,在上述範例中 將一個 HTML 區塊轉換為 DOM 樹狀結構大約需要 5 毫秒如果是較大的網頁,這項程序可能需要更長的時間。在建立流暢的動畫時,如果瀏覽器必須處理大量 HTML,這可能會成為瓶頸。

DOM 樹狀結構會擷取文件標記的屬性和關係, 但不會告知元素算繪後的外觀。這就是 CSSOM 的責任。

CSS 物件模型 (CSSOM)

瀏覽器建構基本頁面的 DOM 時, 參照外部 CSS 的文件 <head> 中的 <link> 元素 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:

CSSOM 建構步驟

CSS 位元組會轉換為字元、符記和節點,最後連結成稱為「CSS 物件模型」(CSSOM) 的樹狀結構:

CSSOM 樹狀結構

CSSOM 為何採用樹狀結構?在為網頁上的任何物件計算最終樣式組合時,瀏覽器會從適用於該節點的最一般規則開始 (例如,如果該節點是 body 元素的子項,則會套用所有 body 樣式),然後透過套用更明確的規則遞迴式精進已計算的樣式,也就是「依序套用」規則。

為了更具體地說明這項概念,請參考先前所述的 CSSOM 樹狀結構。放置在 body 元素內的 <span> 標記中,任何包含的文字都會顯示 16 像素的字型大小,並以紅色顯示文字 - font-size 指令會從 body 向下依序連結至 span。不過,如果 span 是段落 (p) 標記的子項,則不會顯示其內容。

另請注意,先前所述的樹狀結構並非完整的 CSSOM 樹狀結構,只會顯示我們決定在樣式表格中覆寫的樣式。每個瀏覽器都會提供一組預設樣式,也稱為「使用者代理程式樣式」。如果我們未提供任何樣式,瀏覽器就會顯示這些預設樣式,而我們的樣式會覆寫這些預設樣式。

如要瞭解 CSS 處理作業所需的時間,您可以在 DevTools 中記錄時間軸,然後尋找「Recalculate Style」事件:與 DOM 剖析不同,時間軸不會顯示個別的「Parse CSS」項目,而是擷取剖析和 CSSOM 樹狀結構的資訊,並在單一事件下對計算樣式進行遞迴計算。

在開發人員工具中追蹤 CSSOM 結構

我們的瑣碎樣式頁面需要約 0.6 毫秒的處理時間,並影響網頁上的八個元素,雖然影響不大,但仍會造成一些負擔。不過,這八個元素的來源為何?CSSOM 和 DOM 是獨立的資料結構! 原來是瀏覽器隱藏了重要的步驟。接下來,我們將介紹轉譯樹狀結構,將 DOM 和 CSSOM 連結在一起。

意見回饋