宣布變異事件的淘汰和移除計畫,並分享如何在 2024 年 7 月移除前遷移程式碼。
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 年。
為何移除突變事件
不同瀏覽器對突變事件的支援情形各異。部分事件 (例如 DOMNodeInsertedIntoDocument
和 DOMNodeRemovedFromDocument
) 並未在所有瀏覽器中支援。對於其他事件,由於缺乏任何約定的規格,因此特定行為會有所不同。不過,一個合理的問題可能是:既然他們「完成」了,反而只會拖慢了有問題的網頁,為什麼不就只是放進去呢?答案分為兩部分。
首先,這些事件會阻礙網頁平台的發展。隨著網路的演進,新的 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 套件中。
- https://github.com/mfreed7/mutation-events-polyfill#readme
- https://www.npmjs.com/package/mutation-events
時程和淘汰前測試資訊
所有使用者* 的 Chrome 127 版將移除突變事件*,該版本將於 2024 年 7 月 23 日推出穩定版。提前警告,這類活動會提前從 Canary、開發人員版和 Beta 版中移除。