大型 DOM 大小對互動性的影響可能比您想像中還大。本指南將說明原因,以及您可以採取的行動。
這是無法避免的:您建立網頁時,該網頁一定會有文件物件模型 (DOM)。DOM 代表網頁的 HTML 結構,並提供 JavaScript 和 CSS 對網頁結構和內容的存取權。
不過,DOM 的大小會影響瀏覽器快速有效率地算繪網頁。一般來說,DOM 越大,網頁的初始算繪成本就越高,且在網頁生命週期中更新算繪的成本也越高。
如果網頁的 DOM 很大,而修改或更新 DOM 的互動會觸發耗用資源的版面配置工作,進而影響網頁的快速回應能力,就會造成問題。耗費資源的版面配置工作可能會影響網頁的與下一個顯示的內容互動 (INP) 指標。如要讓網頁快速回應使用者互動,請務必確保 DOM 大小僅為必要大小。
網頁的 DOM 過大是什麼意思?
根據 Lighthouse,網頁的 DOM 節點超過 1,400 個時,DOM 大小就會過大。當網頁的 DOM 超過 800 個節點時,Lighthouse 就會開始發出警告。以下列 HTML 為例:
<ul>
<li>List item one.</li>
<li>List item two.</li>
<li>List item three.</li>
</ul>
在上述程式碼中,有四個 DOM 元素:<ul>
元素,以及其三個 <li>
子項元素。您的網頁節點幾乎一定比這個多,因此請務必瞭解如何控管 DOM 大小,以及在網頁 DOM 盡可能縮小後,可採取哪些策略來最佳化算繪作業。
大型 DOM 對網頁效能有何影響?
大型 DOM 會透過下列幾種方式影響網頁效能:
- 網頁的初始轉譯期間。將 CSS 套用至網頁時,系統會建立類似於 DOM 的結構,也就是 CSS 物件模型 (CSSOM)。CSS 選取器越具體,CSSOM 就越複雜,繪製網頁到螢幕上所需的版面配置、樣式、合成和繪製工作就越耗時。這項額外工作會增加網頁載入初期發生的互動延遲。
- 當互動修改 DOM 時 (無論是插入或刪除元素,或是修改 DOM 內容和樣式),更新作業的算繪工作可能會導致版面配置、樣式、合成和繪製工作成本高昂。與網頁的初始算繪情況相同,如果 CSS 選擇器明確度提高,當 HTML 元素因互動而插入 DOM 時,算繪工作就會增加。
- 當 JavaScript 查詢 DOM 時,系統會將 DOM 元素的參照儲存在記憶體中。舉例來說,如果您呼叫
document.querySelectorAll
選取網頁上的所有<div>
元素,如果結果傳回大量 DOM 元素,記憶體成本可能會相當高。
這些因素都會影響互動性,但上述清單中的第二項尤其重要。如果互動導致 DOM 發生變化,可能會觸發大量工作,進而導致網頁的 INP 偏低。
如何測量 DOM 大小?
您可以透過幾種方式測量 DOM 大小。第一種方法是使用 Lighthouse。執行稽核時,目前頁面 DOM 的統計資料會顯示在「診斷」標題下方的「避免 DOM 過大」稽核中。這個部分會顯示 DOM 元素總數、包含最多子元素的 DOM 元素,以及最深層的 DOM 元素。
較簡單的方法是使用任何主要瀏覽器的開發人員工具中的 JavaScript 控制台。如要取得 DOM 中的 HTML 元素總數,請在網頁載入後,於控制台中使用下列程式碼:
document.querySelectorAll('*').length;
如要即時查看 DOM 大小更新,也可以使用效能監控工具。使用這項工具,您可以將版面配置和樣式作業 (以及其他效能層面) 與目前的 DOM 大小建立關聯。
如果 DOM 的大小即將達到 Lighthouse DOM 大小的警告門檻,或完全失敗,下一步就是找出如何縮減 DOM 的大小,提升網頁回應使用者互動的能力,進而改善網站的 INP。
如何評估互動影響的 DOM 元素數量?
如果您在實驗室中分析緩慢的互動,並懷疑可能與網頁的 DOM 大小有關,可以選取分析器中標示為「重新計算樣式」的任何活動,並觀察底部面板中的脈絡資料,找出受影響的 DOM 元素數量。
從上方的螢幕截圖中,可以看到工作樣式重新計算時 (選取時),會顯示受影響的元素數量。上方的螢幕截圖顯示 DOM 大小對網頁轉譯作業的影響,其中包含許多 DOM 元素,但無論如何,這項診斷資訊都很有用,可判斷 DOM 大小是否為限制因素,導致系統需要較長時間才能在互動後繪製下一個影格。
如何縮減 DOM 大小?
除了稽核網站 HTML 中不必要的標記外,減少 DOM 大小的主要方法是減少 DOM 深度。如果瀏覽器開發人員工具的「元素」分頁中顯示類似下列的標記,可能表示 DOM 深度不必要地過深:
<div>
<div>
<div>
<div>
<!-- Contents -->
</div>
</div>
</div>
</div>
如果看到類似模式,您或許可以簡化這些模式,方法是將 DOM 結構扁平化。這樣做可減少 DOM 元素數量,並簡化網頁樣式。
DOM 深度也可能是您所用架構的徵兆。特別是,以元件為基礎的架構 (例如依賴 JSX 的架構) 需要您在父項容器中巢狀嵌入多個元件。
不過,許多架構都允許您使用所謂的片段,避免巢狀元件。提供片段做為功能的元件架構包括 (但不限於) 下列項目:
在所選架構中使用片段,即可減少 DOM 深度。如果您擔心 DOM 結構扁平化會對樣式造成影響,不妨使用更先進 (也更快速) 的版面配置模式,例如 彈性方塊或格線。
其他策略
即使您費盡心思簡化 DOM 樹狀結構,並移除不必要的 HTML 元素,盡可能縮小 DOM,但 DOM 仍可能相當龐大,且在因應使用者互動而變更時,會觸發大量算繪作業。如果遇到這種情況,可以考慮採用其他策略來限制算繪作業。
考慮採用加法方法
您可能遇到這種情況:網頁首次算繪時,使用者一開始看不到網頁的大部分內容。這或許是延遲載入 HTML 的好機會,您可以在啟動時省略 DOM 的這些部分,但當使用者與需要網頁初始隱藏部分的網頁互動時,再加入這些部分。
這項做法在初始載入期間和之後都可能很有用。在初始網頁載入時,您會減少預先進行的算繪工作,這表示初始 HTML 酬載會較輕,且算繪速度會更快。這樣一來,在關鍵期間的互動就有更多機會執行,且主執行緒的注意力競爭較少。
如果網頁有許多部分在載入時會先隱藏,這也有助於加快觸發重新算繪作業的其他互動。不過,隨著其他互動在 DOM 中新增更多內容,DOM 在整個網頁生命週期中不斷成長,因此算繪工作也會增加。
隨著時間推移新增至 DOM 可能很棘手,而且有其自身的取捨。如果您採用這種做法,很可能需要發出網路要求,取得資料來填入 HTML,以便回應使用者互動,並將 HTML 新增至網頁。雖然進行中的網路要求不會計入 INP,但可能會增加感知延遲。如果可以,請顯示載入微調器或其他指標,讓使用者瞭解系統正在擷取資料。
限制 CSS 選擇器複雜度
瀏覽器剖析 CSS 中的選取器時,必須遍歷 DOM 樹狀結構,才能瞭解這些選取器如何 (以及是否) 適用於目前的版面配置。這些選取器越複雜,瀏覽器就必須執行更多工作,才能完成網頁的初始算繪,而且如果網頁因互動而變更,瀏覽器也必須重新計算樣式並執行版面配置工作。
使用 content-visibility
屬性
CSS 提供 content-visibility
屬性,可有效延遲轉譯畫面外的 DOM 元素。元素接近可視區域時,系統會視需要算繪元素。content-visibility
的優點不僅在於大幅減少初始網頁算繪作業,當使用者互動導致網頁 DOM 變更時,也能略過螢幕外元素的算繪作業。
結論
將 DOM 大小縮減至僅包含必要項目,是改善網站 INP 的好方法。這樣做可以減少瀏覽器在 DOM 更新時執行版面配置和轉譯工作所花費的時間。即使無法有效縮減 DOM 大小,您還是可以運用一些技巧,將轉譯作業隔離到 DOM 子樹狀結構,例如 CSS 容器和 content-visibility
CSS 屬性。
無論採用哪種做法,只要盡量減少算繪工作,並減少網頁因應互動而執行的算繪工作量,使用者與網站互動時,就會覺得網站回應速度更快。這表示網站的 INP 會降低,使用者體驗也會提升。