События мутации будут удалены из Chrome.

Объявляем о прекращении поддержки и планируемом удалении событий мутации, а также рассказываем, как вы можете перенести свой код до удаления в июле 2024 года.

Мейсон Фрид
Mason Freed

Chromium официально объявил устаревшими события мутации и планирует прекратить поддержку, начиная с версии 127 , стабильная версия которой выйдет 23 июля 2024 года . В этом посте объясняется, почему мы удаляем события мутации, и предлагается путь миграции до того, как они будут удалены из браузера.

Что такое мутационные события?

События мутации — это название следующей коллекции событий:

  • 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 , поддерживаются не всеми браузерами. Для других событий конкретное поведение варьируется из-за отсутствия какой-либо согласованной спецификации. Однако может возникнуть резонный вопрос: почему бы просто не оставить их там, поскольку они «готовы» и только замедляют страницы, которые их используют? Ответ состоит из двух частей.

Во-первых, эти события сдерживают развитие веб-платформы. По мере развития Интернета и добавления новых 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 , обратите внимание, что он может обрабатывать все мутации, происходящие во всем дереве, за один вызов, вместо того, чтобы требовать нескольких вызовов обработчика событий.

Полифилл

Существует полифилл, который пытается позволить существующему коду продолжать работу, работая при этом от MutationObserver . Полифил находится на GitHub или в виде пакета npm.

Информация о сроках и прекращении поддержки пробной версии

События мутаций будут удалены из Chrome 127 для всех пользователей*, которые перейдут в стабильную версию 23 июля 2024 года. События начнут удаляться из каналов Canary, Dev и Beta раньше этого срока в качестве раннего предупреждения.

  • Если вам нужно дополнительное время (после июля 2024 г.) для переноса кода, существует пробная версия устаревания , которая временно повторно включает события на определенных сайтах. Существует также корпоративная политика под названием MutationEventsEnabled , которая работает аналогичным образом для корпоративных пользователей. Любой из этих вариантов дает примерно девять месяцев дополнительного времени для миграции, если это необходимо.