ミューテーション イベントのサポート終了と削除予定についてお知らせし、2024 年 7 月の削除までにコードを移行する方法を共有します。
Chromium ではミューテーション イベントが非推奨になり、バージョン 127 以降でサポートを終了する予定です。2024 年 7 月 23 日に Stable リリースに移行します。この記事では、ミューテーション イベントを削除する理由と、ブラウザから削除される前に移行するための方法について説明します。
ミューテーション イベントとは
ミューテーション イベントは、次のイベントのコレクションの名前です。
DOMNodeInserted
DOMNodeRemoved
DOMSubtreeModified
DOMCharacterDataModified
DOMNodeInsertedIntoDocument
DOMNodeRemovedFromDocument
- (最新のブラウザではサポートされていません)
DOMAttrModified
- (最新のブラウザではサポートされていません)
DOMAttributeNameChanged
- (最新のブラウザではサポートされていません)
DOMElementNameChanged
これらのイベントは DOM レベル 2 仕様の非常に古い部分であり、2011 年以降は非推奨となっています。これらは MutationObserver インターフェースに置き換えられました。これは 2013 年以降、すべての最新ブラウザでサポートされています。
ミューテーション イベントの履歴
ミューテーション イベントは昔は良いアイデアのように思えましたが、致命的な欠陥がいくつかあることが判明しました。
- 冗長で、頻繁に実行される。削除されたノードごとにイベントがトリガーされます。
- イベントの伝播と、UA の多くのランタイム最適化を妨げるため、遅いです。
- クラッシュの原因となることがよくあります。イベント リスナーは、実行中の DOM オペレーションの下で DOM 全体を変更できるため、ブラウザで多くのクラッシュやセキュリティ バグの原因となっています。
これらの欠陥のため、これらのイベントは 2011 年に仕様で非推奨となり、2012 年に代替 API(MutationObserver
)が作成されました。新しい API は、この時点で 10 年以上実装され、機能しています。
ミューテーション イベントが削除される理由
ミューテーション イベントのサポートはブラウザによって異なります。DOMNodeInsertedIntoDocument
や DOMNodeRemovedFromDocument
など、一部のイベントはすべてのブラウザでサポートされていません。その他のイベントについては、合意された仕様がないため、具体的な動作は異なります。ただし、合理的な疑問として、それらのタスクは「完了」しており、それらを使用するページの速度を低下させるだけなので、そのままにしておけばよいのではないかという質問が考えられます。回答は 2 つのパートで構成されています。
まず、これらのイベントはウェブ プラットフォームの成長を妨げています。ウェブの進化に伴い新しい API が追加されるにつれ、これらのレガシー API の存在を考慮する必要があります。こうしたイベントをサポートする必要があるだけで、新しい API が提案されないこともあります。たとえば、DOM 内で移動されたときに <iframe>
要素が再読み込みされないようにする機能のリクエストは長い間寄せられていました。しかし、ミューテーション イベントの存在もあって、その作業は達成が困難すぎると判断され、リクエストはクローズされました。
こうしたイベントは、ブラウザの高速化の妨げになっています。ブラウザには、ミューテーション イベントを使用しないページでパフォーマンスの低下を回避するための最適化機能が備わっていますが、それでも完璧ではありません。変更イベント リスナーについては、多くの場所でチェックを行う必要があります。これらのイベントは 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
イベント リスナー コードよりも長く見えますが、イベント ハンドラを複数回呼び出す必要はなく、1 回の呼び出しでツリー全体で発生するすべてのミューテーションを処理できます。
ポリフィル
MutationObserver
を活用しながら、既存のコードを機能させ続けるためのポリフィルがあります。ポリフィルは GitHub または npm パッケージで入手できます。
- https://github.com/mfreed7/mutation-events-polyfill#readme
- https://www.npmjs.com/package/mutation-events
タイムラインと非推奨トライアルに関する情報
2024 年 7 月 23 日に Stable 版としてリリースされる Chrome 127 では、すべてのユーザー* に対してミューテーション イベントが削除されます。早期警告として、Canary、Dev、Beta チャンネルからイベントの削除は 2022 年 1 月より前に開始されます。
- コードの移行に 2024 年 7 月以降も時間が必要な場合は、サポート終了トライアルをご利用ください。このトライアルでは、指定したサイトでイベントが一時的に有効になります。また、企業ユーザーに対して同様に機能する
MutationEventsEnabled
というエンタープライズ ポリシーもあります。どちらのオプションを選択しても、必要に応じて移行に約 9 か月間の猶予が与えられます。