實際上,DOM 大小對互動性影響的程度可能比您想像的更大。本指南將說明原因,以及您可以採取的行動。
這是無法避免的:當您建構網頁時,該網頁就會包含文件物件模型 (DOM)。DOM 代表網頁 HTML 的結構,可讓 JavaScript 和 CSS 存取網頁的結構和內容。
不過,DOM 的大小會影響瀏覽器快速且有效率地轉譯網頁的能力。一般來說,DOM 越大,初始轉譯該網頁的成本就越高,且在網頁生命週期後期更新轉譯作業的成本也會增加。
在 DOM 非常大的網頁中,如果修改或更新 DOM 的互動會觸發耗時的版面配置工作,進而影響網頁快速回應的能力,就會造成問題。耗時的版面配置作業可能會影響網頁的與下一個顯示的內容互動;如果您希望網頁能快速回應使用者互動,請務必確保 DOM 大小僅為必要的大小。
什麼時候網頁的 DOM 會「過大」?
根據 Lighthouse 的說法,如果網頁的 DOM 大小超過 1,400 個節點,就會過大。如果網頁的 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 內容和樣式) 時,轉譯該更新所需的工作可能會導致版面配置、樣式、合成和繪製作業成本過高。就像網頁的初始算繪作業一樣,當 HTML 元素因互動而插入 DOM 時,CSS 選取器的特定性增加可能會增加算繪作業。
- 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 大小有關,您可以選取剖析器中標示為「Recalculate Style」的任何活動,並觀察底部面板中的內容資料,藉此瞭解有多少 DOM 元素受到影響。
請注意,在上述螢幕截圖中,選取作品的樣式重新計算功能後,畫面會顯示受影響的元素數量。雖然上述螢幕截圖顯示 DOM 大小對含有許多 DOM 元素的網頁轉譯作業的影響,但無論如何,這項診斷資訊都很實用,可用於判斷 DOM 大小是否會影響下一個影格回應互動所需的時間。
如何縮減 DOM 大小?
除了檢查網站 HTML 是否有不必要的標記,減少 DOM 深度是縮減 DOM 大小的主要方法。如果在瀏覽器開發人員工具的「Elements」分頁中看到類似以下的標記,就表示 DOM 可能過於深層:
<div>
<div>
<div>
<div>
<!-- Contents -->
</div>
</div>
</div>
</div>
當您看到這種模式時,可以透過扁平化 DOM 結構來簡化。這樣做可減少 DOM 元素數量,並可能讓您有機會簡化網頁樣式。
DOM 深度也可能是您使用的架構的症狀。特別是,以元件為基礎的架構 (例如依賴 JSX 的架構) 需要您在父項容器中巢狀放置多個元件。
不過,許多架構都允許您使用片段,避免巢狀元件。提供片段做為功能的元件式架構包括 (但不限於) 以下項目:
只要在所選架構中使用片段,即可減少 DOM 深度。如果您擔心 DOM 結構扁平化對樣式造成的影響,建議您使用更新 (且更快速) 的版面配置模式,例如 flexbox 或 grid。
其他可考慮的策略
即使您費盡心思將 DOM 樹扁平化,並移除不必要的 HTML 元素,以盡可能縮小 DOM,但 DOM 仍可能相當龐大,並會在回應使用者互動時進行大量轉譯作業。如果您發現自己處於這種情況,可以考慮採用其他策略來限制轉譯工作。
考慮採用加法式方法
您可能會遇到這樣的情況:使用者在網頁首次轉譯時,無法一開始就看到大部分的網頁內容。這可能是使用延遲載入 HTML 的機會,因為您可以在啟動時省略 DOM 的部分,但在使用者與需要網頁初始隱藏部分的網頁部分互動時,再加入這些部分。
這項做法在初始載入期間和之後都很實用。對於初始網頁載入作業,您會事先執行較少的轉譯工作,也就是說,初始 HTML 酬載會變得較輕,且轉譯速度會加快。這樣一來,在該關鍵期間內,互動作業就能有更多機會執行,且不會與主要執行緒爭奪注意力。
如果網頁的許多部分在載入時一開始就處於隱藏狀態,這麼做也能加快觸發重新算繪作業的其他互動。不過,隨著其他互動將更多內容新增至 DOM,DOM 在網頁生命週期內的規模也會增加,因此轉譯工作量也會隨之增加。
隨著時間的推移,新增 DOM 的難度會越來越高,而且會產生一些取捨。如果您採用這種做法,很可能會發出網路要求,以便取得資料,並在使用者互動時,將您想加入網頁的 HTML 填入。雖然傳輸中的網路要求不會計入 INP,但可能會增加感知延遲時間。盡可能顯示載入動畫或其他指標,讓使用者知道系統正在擷取資料,
限制 CSS 選取器的複雜度
當瀏覽器剖析 CSS 中的選取器時,必須遍歷 DOM 樹狀結構,才能瞭解這些選取器是否適用於目前的版面配置,以及如何套用。這些選取器越複雜,瀏覽器就必須執行更多工作,才能執行網頁的初始算繪作業,以及在網頁因互動而變更時,增加樣式重新計算和版面配置的工作。
使用 content-visibility
屬性
CSS 提供 content-visibility
屬性,這是一種有效的方式,可延遲轉譯畫面外的 DOM 元素。當元素接近可視區域時,系統會視需要將其算繪。content-visibility
的優點不僅可在初始網頁轉譯時大幅減少轉譯工作,還可在使用者互動導致網頁 DOM 變更時,略過轉譯畫面外元素的工作。
結論
將 DOM 大小縮減至必要的程度,是改善網站 INP 的好方法。這樣一來,您就能縮短瀏覽器在 DOM 更新時執行版面配置和轉譯作業所需的時間。即使您無法有效縮減 DOM 大小,仍可使用某些技巧將轉譯工作隔離至 DOM 子樹,例如 CSS 容器和 content-visibility
CSS 屬性。
無論您採取何種方式,只要能盡可能減少轉譯工作,並減少網頁在回應互動時所執行的轉譯工作量,使用者在與網站互動時,就會覺得網站更有回應。這表示網站的 INP 會降低,進而提供更優質的使用者體驗。