大型 DOM 大小對互動性的影響,遠比您想的大。本指南將說明原因和建議做法。
如此一來,當您建立網頁時,該網頁就會提供文件物件模型 (DOM),DOM 代表網頁 HTML 的結構,並且可讓 JavaScript 和 CSS 存取網頁結構和內容。
但問題在於 DOM 的 size 會影響瀏覽器能否快速且有效率地轉譯網頁。一般來說,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 類似的結構,也就是 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 的大小有關,您可以在分析器中選取「重新計算樣式」這個分析器中的任一活動,然後觀察底部面板中的內容相關資料,瞭解有多少 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;但如果使用者與網頁初始隱藏部分的互動,則應該加入這些元素。
此方法在初始載入期間,甚至之後可能都很有用。針對初次載入頁面,您減少了前置的算繪工作,這表示初始 HTML 酬載會較快,顯示速度也會更快。這樣一來,重要期間的互動就會增加,爭取主要執行緒注意力的機會。
如果網頁上有許多部分在載入時一開始隱藏,也可能導致其他互動速度加快重新轉譯工作的速度。不過,隨著其他互動在 DOM 中新增更多互動,隨著 DOM 在整個網頁生命週期中逐漸成長,算繪工作也會不斷增加。
隨著時間推移而新增至 DOM 可能不太容易,也各有優缺點。如果您決定執行此路徑,可能會提出網路要求,以便取得資料來填入您要新增至網頁中的 HTML,藉此回應使用者互動。雖然傳輸中的網路要求不會計入 INP,但可能會增加感知延遲時間。如果可以,請顯示載入旋轉圖示或其他表示正在擷取資料的指標,讓使用者瞭解發生了什麼事。
限制 CSS 選取器複雜度
瀏覽器剖析 CSS 中的選取器時,必須週遊 DOM 樹狀結構,瞭解這些選取器會如何套用至目前的版面配置,以及是否符合條件。這些選取器越複雜,瀏覽器為了執行網頁初始轉譯作業需要花費更多心力。此外,如果頁面因互動而改變,樣式重新計算和版面配置也會運作。
使用 content-visibility
屬性
CSS 提供 content-visibility
屬性,可有效地延遲轉譯畫面外的 DOM 元素。元素接近可視區域時,會以隨選方式呈現。content-visibility
的優點不僅可減少初始頁面轉譯作業的大量轉譯工作,而且當網頁 DOM 因使用者互動而變更時,會略過螢幕外元素的轉譯工作。
結論
若要最佳化網站的 INP,建議您只在必要時縮減 DOM 大小。這樣可以減少 DOM 更新時,瀏覽器執行版面配置和轉譯工作所需的時間。即使您無法有效縮減 DOM 大小,您也可以使用一些技巧,將轉譯工作隔離於 DOM 子樹狀結構,例如 CSS 隔離和 content-visibility
CSS 屬性。
無論如何,建立能盡量減少轉譯工作的環境,以及減少網頁回應互動的轉譯工作量,您的網站在使用者與這些互動時,會得到更多回應。也就是說,網站的 INP 數量會較低,且可帶來更優質的使用者體驗。
主頁橫幅由 Louis Reed 製作,內容為「Unsplash」。