Announcing the deprecation and planned removal of mutation events, and sharing how you can migrate your code before the removal in July 2024.
Chromium has officially deprecated mutation events, and has a plan to remove support starting with version 127, which goes to stable release on July 23, 2024. This post explains why we are removing mutation events, and provides a path for migrating before they are removed from the browser.
What are mutation events?
Mutation events is the name for the following collection of events:
DOMNodeInserted
DOMNodeRemoved
DOMSubtreeModified
DOMCharacterDataModified
DOMNodeInsertedIntoDocument
DOMNodeRemovedFromDocument
- (Not supported by any modern browser)
DOMAttrModified
- (Not supported by any modern browser)
DOMAttributeNameChanged
- (Not supported by any modern browser)
DOMElementNameChanged
These events are a very old part of the DOM level 2 spec, and they have been deprecated since 2011. They were replaced by the MutationObserver interface, which has been supported in all modern browsers since 2013.
History of mutation events
Mutation events sounded like a good idea a long ago, but turned out to have several fatal flaws:
- They are verbose and fire too often. An event is fired for each node that is removed.
- They are slow, due to event propagation and because they prevent many UA run-time optimizations.
- They frequently cause crashes. They have been the source of many crashes and security bugs in browsers, because event listeners can change the entire DOM underneath a running DOM operation.
Because of these flaws, the events were deprecated from the spec in 2011 and a replacement API (MutationObserver
) was constructed in 2012. The new API has been implemented and functional for over 10 years at this point.
Why mutation events are being removed
Support for mutation events varies across browsers. Some events, for example DOMNodeInsertedIntoDocument
and DOMNodeRemovedFromDocument
, are not supported in all browsers. For the other events, the particular behavior varies due to the lack of any agreed specification. However, a reasonable question might be: why not just leave them there, since they're "done" and they only slow down pages that use them? The answer comes in two parts.
Firstly, these events are holding back the web platform. As the web evolves, and new APIs are added, the existence of these legacy APIs has to be taken into account. Sometimes, just the need to support these events can keep new APIs from being proposed. As one example, there has been a longstanding request to prevent <iframe>
elements from reloading when they are moved within the DOM. However, partially due to the existence of mutation events, that effort was deemed to be too difficult to achieve, and the request was closed.
These events continue to get in the way of making browsers faster. Even with the optimizations that browsers have, which attempt to avoid the performance penalties on pages that do not use mutation events, things are not perfect. Checks still need to be made in many places for Mutation Event listeners. Code still needs to be written very defensively, since these events can change the DOM in surprising ways.
Since it has been over 10 years since the events were officially deprecated, and the replacement API has similarly been available for over 10 years, the time has come to finally remove the mutation events from browsers once and for all.
How to migrate
Use MutationObserver
instead
The documentation for MutationObserver
is located on MDN, and is fairly complete. Replacement for your codebase depends on how these events are being used, but as an example:
// 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});
While the MutationObserver
code appears larger than the original DOMNodeInserted
event listener code, notice that it can handle all mutations that happen over an entire tree in one call, rather than requiring multiple calls to the event handler.
Polyfill
There is a polyfill that attempts to allow existing code to continue functioning, while being powered by MutationObserver
. The polyfill is located on GitHub or as an npm package.
- https://github.com/mfreed7/mutation-events-polyfill#readme
- https://www.npmjs.com/package/mutation-events
Timeline and deprecation trial information
Mutation events will be removed from Chrome 127 for all users* which will go to Stable release on July 23, 2024. The events will begin to be removed from Canary, Dev, and Beta channels earlier than that, as an early-warning.
- If you need additional time (beyond July, 2024) to migrate your code, there is a Deprecation Trial which re-enables the events temporarily on specified sites. There is also an Enterprise Policy called
MutationEventsEnabled
that functions in a similar way for enterprise users. Either of these options gives roughly nine months of extra time to migrate, if needed.