Как оптимизировать изменения в DOM для снижения затрат ресурсов
Что проверяют
Понимаете ли вы, что дорого стоит не само изменение DOM, а пересчёт стилей, раскладка и отрисовка, которые оно запускает. Следом обычно просят объяснить layout thrashing на примере и показать, как найти проблему в DevTools.
Как отвечать
Начните с конвейера браузера: стили, layout, paint, composite. Чем раньше в цепочке срабатывает изменение, тем оно дороже. Дальше приёмы:
- чтения отдельно от записей:
offsetHeight,getBoundingClientRect()иgetComputedStyleпосле изменений заставляют браузер пересчитать раскладку немедленно. Чередование чтения и записи в цикле даёт forced reflow на каждой итерации. Сначала прочитайте всё, потом запишите, записи удобно собрать вrequestAnimationFrame; - пакетная вставка:
DocumentFragment,append(...nodes)илиreplaceChildrenвместо тысячиappendChildв живое дерево; - классы вместо стилей:
classList.toggleвместо нескольких присваиванийelement.style; - анимация через
transformиopacity: их обрабатывает композитор без раскладки, аtop,left,widthзапускают layout на каждом кадре.will-changeставьте точечно, каждый слой ест память; - меньше узлов: виртуализация длинных списков через TanStack Virtual или react-window,
content-visibility: autoдля блоков вне экрана,containдля изоляции поддерева; - меньше рендеров во фреймворке: в React это
memo, стабильные ключи, состояние ниже по дереву.
Проверяется всё во вкладке Performance в Chrome DevTools: длинные задачи, фиолетовые блоки Layout и предупреждения о forced reflow.
Где спотыкаются
Говорят, что виртуальный DOM быстрее прямой работы с DOM. Он избавляет от ручного отслеживания изменений, но точечная правка одного узла руками всегда дешевле диффа плюс та же правка.
Пишут innerHTML += в цикле. Браузер каждый раз разбирает всю разметку заново, существующие узлы теряют обработчики, а с пользовательскими данными это ещё и XSS.
Выдают делегирование событий за оптимизацию изменений DOM. Оно экономит память на обработчиках, но число пересчётов раскладки не меняет.