大型 DOM 大小對互動性的影響比想像中還大。本指南將說明原因與可採取的行動。
宇宙不幸,當您建立網頁時,該網頁就會具有文件物件模型 (DOM)。DOM 代表您網頁 HTML 的結構,可讓 JavaScript 和 CSS 存取網頁的結構和內容。
但問題是,DOM 的「大小」會影響瀏覽器快速且有效率的頁面算繪能力。一般來說,DOM 越大,一開始轉譯網頁的時間就越貴,之後在頁面生命週期中更新其轉譯方式時,就會花費較多成本。
在 DOM 過大的網頁上,如果互動修改或更新 DOM 會觸發費用高昂的版面配置,導致網頁的回應速度變慢,就會發生這種情況。過多的版面配置工作可能會影響網頁的與下一個顯示的內容互動 (INP);如果您希望網頁能快速回應使用者互動,就必須確保 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 類似的結構,稱為 CSSOM 物件模型。隨著 CSS 選取器的明確性增加,CSSOM 會變得更加複雜,因此需要更多時間執行必要的版面配置、樣式、合成和繪製工作,將網頁繪製到螢幕上。這種做法會使在網頁載入期間早期發生的互動,增加互動延遲。
- 當互動透過元素插入或刪除方式修改 DOM,或是修改 DOM 內容和樣式時,轉譯該更新所需的工作可能會導致版面配置、樣式、撰寫和繪製工作會耗用大量資源。與頁面的初始算繪不同,當 HTML 元素因互動而插入 DOM 時,CSS 選取器的明確性會提高,顯示出來。
- 當 JavaScript 查詢 DOM 時,DOM 元素的參照會儲存在記憶體中。舉例來說,如果您呼叫
document.querySelectorAll
來選取頁面上所有的<div>
元素,如果結果傳回大量 DOM 元素,就可能會消耗記憶體費用。
![螢幕截圖顯示 Chrome 開發人員工具「效能」面板中的轉譯工作過多造成的長時間工作。長時間工作的呼叫堆疊會顯示大量時間重新計算頁面樣式以及預先繪製。](https://web.developers.google.cn/static/articles/dom-size-and-interactivity/image/a-screenshot-a-long-task-a768ec4a643a9.png?authuser=19&hl=zh-tw)
以上所有這些因素都會影響互動性,但上方清單中第二個項目有特定的重要性。如果互動導致 DOM 改變,就會啟動許多可能導致網頁上的 INP 不佳的工作。
如何測量 DOM 大小?
您可以透過幾種方式測量 DOM 大小。第一種方式是使用 Lighthouse。執行稽核時,目前網頁 DOM 的統計資料會顯示「避免過度使用 DOM 大小」請前往「診斷」分頁標題。在本節中,您會看到 DOM 元素總數、內含最多子項元素的 DOM 元素,以及最深的 DOM 元素。
更簡單的方法是在任何主要瀏覽器中,使用開發人員工具中的 JavaScript 控制台。如要取得 DOM 中的 HTML 元素總數,您可以在頁面載入後,在控制台中使用以下程式碼:
document.querySelectorAll('*').length;
如要即時查看 DOM 大小更新,也可以使用效能監控工具。使用這項工具,即可為版面配置和樣式作業 (和其他效能層面) 與目前的 DOM 大小建立關聯。
![Chrome 開發人員工具中的效能監控器螢幕截圖。您可以在網頁的生命週期內,持續監控網頁成效的各種面向。在螢幕截圖中,我們會持續監控 DOM 節點的數量、每秒版面配置數和每個區段的樣式重新計算。](https://web.developers.google.cn/static/articles/dom-size-and-interactivity/image/a-screenshot-the-perform-d46dd7f32a5de.png?authuser=19&hl=zh-tw)
如果 DOM 的大小接近 Lighthouse DOM 大小的警告門檻或完全失敗,下一步就是設法縮減 DOM 的大小,以提升網頁回應使用者互動的能力,好讓網站的 INP 能改善。
如何測量受互動影響的 DOM 元素數量?
如果您正在研究室中分析速度緩慢的互動,並懷疑可能與頁面 DOM 的大小相關,不妨在分析器中選取「重新計算樣式」的任何活動,瞭解有多少 DOM 元素受到影響。並觀察底部面板中的比對內容資料
![在 Chrome 開發人員工具的「效能」面板中,選取樣式重新計算活動的螢幕截圖。互動軌在頂端顯示點擊互動,大部分工作都花在重新計算樣式和預先繪製。畫面底部會顯示所選活動的詳細資料,當中有 2,547 個 DOM 元素受到影響。](https://web.developers.google.cn/static/articles/dom-size-and-interactivity/image/a-screenshot-selected-st-9a6c0cc217aa3.png?authuser=19&hl=zh-tw)
在上方的螢幕截圖中,您會發現當選取項目時,系統重新計算工作的樣式數量,會顯示受影響的元素數量。以上螢幕截圖顯示 DOM 大小在內含多個 DOM 元素的網頁轉譯作業中, DOM 大小影響極大情況,但這項診斷資訊就十分實用,有助於判斷 DOM 大小是否為回應互動後,下一個影格繪製所需的時間長度限制。
如何縮減 DOM 大小?
除了審核網站的 HTML 是否有不必要的標記之外,減少 DOM 大小的主要方式,是降低 DOM 深度。這可能是因為您在瀏覽器開發人員工具的「Elements」Elements分頁中,看到類似以下的標記時,DOM 才是不必要的深度:
<div>
<div>
<div>
<div>
<!-- Contents -->
</div>
</div>
</div>
</div>
看到這類模式時,您可以壓平 DOM 結構來簡化這些模式。這樣可以減少 DOM 元素數量,讓您有機會簡化網頁樣式。
DOM 深度也可能是您所使用的架構的症狀。尤其是以元件為基礎的架構 (例如仰賴 JSX 的架構),您必須在父項容器中建立多個元件的巢狀結構。
不過,許多架構可讓您使用所謂的片段,避免建立巢狀結構元件。提供片段做為功能的元件式架構包括但不限於:
在您選擇的架構中使用片段,可降低 DOM 深度。如果您擔心整併 DOM 結構對樣式的影響,使用更現代化 (且速度更快) 的版面配置模式 (例如 flexbox 或 Grid) 可能會有幫助。
其他建議策略
即使您對於壓平 DOM 樹狀結構並移除不必要的 HTML 元素來盡可能縮小 DOM 而減少 DOM,它會因為使用者互動行為改變而產生大量轉譯工作。假如您在這個職位,可考慮限制顯示網頁的功能。
考慮加入其他方式
某個位置,很有可能在網頁一開始轉譯時,使用者無法看見網頁內容。若是在啟動時省略 DOM 的部分,即有機會延遲載入 HTML,但當使用者與網頁中需要網頁初始隱藏元素的部分互動時,加入這些部分即可。
此方法在初始載入期間或之後可能都非常實用。在初次載入網頁的過程中,您所需的轉譯工作較少,也就是說,初始的 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 會較低,進而改善使用者體驗。
主頁橫幅由 Louis Reed 提供,來源為 Unsplash。