異動事件將從 Chrome 中移除

宣布變異事件的淘汰和移除計畫,並分享如何在 2024 年 7 月移除前遷移程式碼。

Mason Freed
Mason Freed

Chromium 已正式淘汰突變事件,並計劃從 127 版開始移除支援,該版本將於 2024 年 7 月 23 日推出穩定版。本文將說明我們移除變異事件的原因,並在變異事件從瀏覽器移除前,提供遷移路徑。

什麼是異動事件?

變異事件是下列事件集合的名稱:

  • DOMNodeInserted
  • DOMNodeRemoved
  • DOMSubtreeModified
  • DOMCharacterDataModified
  • DOMNodeInsertedIntoDocument
  • DOMNodeRemovedFromDocument
  • (任何新式瀏覽器皆不支援) DOMAttrModified
  • (任何新式瀏覽器皆不支援) DOMAttributeNameChanged
  • (任何新式瀏覽器皆不支援) DOMElementNameChanged

這些事件是 DOM 級別 2 規格中非常舊的部分,且自 2011 年起已淘汰。由 MutationObserver 介面取代,自 2013 年起,所有新式瀏覽器都支援

變化事件記錄

變異事件在很久以前聽起來是個好點子,但實際上有幾個致命缺陷

  • 它們太冗長,而且觸發頻率過高。系統會針對每個移除的節點觸發事件。
  • 由於事件傳播,並使通用 Analytics 執行階段最佳化無法進行多項最佳化作業,因此速度較慢
  • 經常造成當機。由於事件監聽器可以變更執行中的 DOM 作業底下的整個 DOM,因此對瀏覽器而言,這些當機問題已成為許多瀏覽器當機和安全性錯誤的來源。

由於這些缺陷,這些事件在 2011 年已淘汰,並在 2012 年建構了替換 API (MutationObserver)。新版 API 已實作並運作超過 10 年。

為何移除突變事件

不同瀏覽器對突變事件的支援情形各異。部分事件 (例如 DOMNodeInsertedIntoDocumentDOMNodeRemovedFromDocument) 並未在所有瀏覽器中支援。對於其他事件,由於缺乏任何約定的規格,因此特定行為會有所不同。不過,一個合理的問題可能是:既然他們「完成」了,反而只會拖慢了有問題的網頁,為什麼不就只是放進去呢?答案分為兩部分。

首先,這些事件會阻礙網頁平台的發展。隨著網路的演進,新的 API 也隨之增加,因此必須考量這些舊版 API 的存在。有時,只要需要支援這些事件,就可能無法提出新的 API。舉例來說,長期以來都有人提出要求,希望在 <iframe> 元素在 DOM 中移動時,系統不要重新載入該元素。不過,部分原因是因為變異事件的存在,因此我們認為這項工作難以完成,因此關閉了這項要求。

這類事件不斷擴大瀏覽器運作速度。即使瀏覽器已進行最佳化,試圖避免未使用突變事件的網頁發生效能懲罰,但仍無法完全避免。但 Mutation Event 事件監聽器仍需要在許多地方進行檢查。程式碼仍需以最具防禦力的方式編寫,因為這類事件可能會以驚人的方式變更 DOM。

這些事件正式淘汰已超過 10 年,且替換 API 也已推出超過 10 年,因此現在是時候從瀏覽器中徹底移除變異事件。

如何遷移

改用 MutationObserver

MutationObserver 說明文件位於 MDN 上,且完整內容完整。程式碼基底的替換方式取決於這些事件的使用方式,但舉例來說:

// Old mutation event usage:  
target.addEventListener('DOMNodeInserted',event => doSomething(event.target));

// Replacement mutation observer code:  
const observer = new MutationObserver(mutationList =>  
  mutationList.filter(m => m.type === 'childList').forEach(m => {  
    m.addedNodes.forEach(doSomething);  
  }));  
observer.observe(target,{childList: true, subtree: true});  

雖然 MutationObserver 程式碼看起來比原始 DOMNodeInserted 事件監聽器程式碼大,但請注意,它可以處理在單一呼叫中整個樹狀結構發生的所有異動,無須對事件處理常式多次呼叫。

聚酯纖維

有一個 polyfill 會嘗試讓現有程式碼在 MutationObserver 的支援下繼續運作。polyfill 位於 GitHub 或 npm 套件中。

時程和淘汰前測試資訊

所有使用者* 的 Chrome 127 版將移除突變事件*,該版本將於 2024 年 7 月 23 日推出穩定版。提前警告,這類活動會提前從 Canary、開發人員版和 Beta 版中移除。

  • 如果您需要更多時間 (超過 2024 年 7 月) 來遷移程式碼,可以使用淘汰前測試版,在指定網站上暫時重新啟用事件。另外,還有一個名為 MutationEventsEnabled企業政策,對企業版使用者來說,功能類似。無論選擇哪一種方式,您都還會有大約九個月的時間進行遷移作業 (視需要而定)。