ミューテーション イベントのサポート終了と削除予定についてお知らせし、2024 年 7 月の削除までにコードを移行する方法を共有します。
Chromium ではミューテーション イベントが正式に非推奨となっており、2024 年 7 月 23 日に安定版リリースとなるバージョン 127 以降のサポートを終了する予定です。この投稿では、ミューテーション イベントを削除する理由を説明し、ブラウザから削除される前に移行するためのパスを提供します。
ミューテーション イベントとは
ミューテーション イベントは、次のイベントのコレクションの名前です。
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 が提案されないこともあります。一例として、<iframe>
要素が DOM 内で移動される際にその要素が再読み込みされないようにするという長期にわたるリクエストがありました。しかし、ミューテーション イベントの存在などにより、その作業は達成が難しすぎると見なされ、リクエストはクローズされました。
こうしたイベントは、ブラウザの高速化の妨げになっています。ブラウザには、ミューテーション イベントを使用しないページでパフォーマンスの低下を回避するための最適化機能が備わっていますが、それでも完璧ではありません。変更イベント リスナーについては、多くの場所でチェックを行う必要があります。これらのイベントは 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
タイムラインと非推奨トライアルに関する情報
すべてのユーザーの Chrome 127 からミューテーション イベントが削除され*、2024 年 7 月 23 日に Stable リリースに移行します。早期警告として、Canary、Dev、Beta チャンネルからイベントの削除は 2022 年 1 月 1 日より前に開始されます。
- コードの移行に時間が必要な場合は(2024 年 7 月以降)、デプリケーション トライアルを利用すると、指定したサイトでイベントを一時的に再度有効にできます。
MutationEventsEnabled
というエンタープライズ ポリシーもあります。これは、企業ユーザーに対して同様に機能します。どちらのオプションを選択しても、必要に応じて移行に約 9 か月間の猶予が与えられます。