DOM медленный. DOM не медленный. — 8 июня 2026 г. в 11:57:36.140
DOM медленный. DOM не медленный. Знаете, помню, когда React только набирал популярность, был один доклад с кликбейтным названием «DOM медленный». И его подхватило волной хайпа. Никто толком ни в чем не разобрался, но все повторяли как мантру: «DOM медленный, VDOM быстрый». А потом хайпанул Svelte и сделал свой доклад, где говорил, что это величайшее заблуждение и DOM на самом деле быстрый. Опять никто ни в чем не разобрался, но стали повторять тезисы из новой методички. Меня этот момент всегда удивлял, но такова жизнь. Хороший маркетинг должен быть построен так, чтобы звучало эффектно и не вызывало вопросов. Но давайте разберемся, что же всё-таки имелось в виду в тезисе «DOM медленный» и зачем нужен VDOM. А потом поймем, что имелось в виду в тезисах Svelte. Итак, правда в том (хотя, думаю, это никого не удивит), что от DOM нам никуда не деться и на самом деле он работает достаточно быстро и хорошо. Это с одной стороны. А с другой — у нас есть UI-библиотеки с автоматической синхронизацией состояния и представления. Говоря проще: поменял состояние — и произошел ререндер, «реактивность, ептыть». Но как эту самую синхронизацию реализовать? А вот ответ на этот вопрос и содержит в себе ответы на все остальное. Дело в том, что способов много, и у каждого свои плюсы. Начнем с самого наивного: у нашего компонента есть рендер-функция, её вызов просто возвращает новое DOM-дерево, которое заменяет старое. Очевидно, что данный подход страшно неэффективен в ситуациях, когда поменялось всего одно свойство или фрагмент текста — DOM медленный. Поэтому стали делать немного иначе: рендер-функция всё еще возвращает новое DOM-дерево, затем оно рекурсивно сравнивается с текущим, и изменения точечно применяются к представлению. Это уже лучше, но проблема всё равно есть: при каждом вызове рендер-функции создается новое DOM-дерево, затем оно обходится — это неэффективно, DOM медленный. Хотя нам, по сути, DOM-дерево тут и не нужно — нам нужно просто обойти деревья и понять, что поменялось. Вот тут и появляется идея VDOM, которую популяризировал React: вместо создания настоящих DOM-деревьев он стал создавать обычные JS-объекты и сравнивать уже их, а затем уже применять изменения. И это действительно намного быстрее. DOM-узлы являются внешним API браузера, у них своя богатая семантика и спецификация, следование которой не бесплатно. А JS-объекты — это маленькие кирпичики языка, которые VM умеют очень быстро создавать. Вот и получается, что «DOM медленный» — это про ситуацию, когда для нахождения изменений строится новое дерево и затем сравнивается с исходным, и работает это куда хуже, чем если просто использовать объекты. А что же тогда имел в виду Svelte? А то, что сравнение деревьев — не единственный способ обновления представления. Можно статически на этапе сборки преобразовать код так, чтобы такие сравнения были не нужны. Или можно точечно подвязываться к обновлению конкретных узлов, но уже в рантайме. У каждого способа свои плюсы и минусы. Поэтому в реальности мы видим сближение крупных игроков в сторону общего знаменателя. Получаются этакие гибриды. Но вернемся к React: дело в том, что подход с VDOM оптимизирует, но не лечит проблемы сравнения деревьев. У нас всё еще есть как минимум две проблемы. Во-первых, вызов рендер-функции на каждом обновлении — это сам по себе вызов функции (а внутри нее может быть много чего). Плюс это вызывает перестройку дерева, пускай и виртуального. Во-вторых, сравнение виртуальных деревьев всё еще может вызвать фриз, если деревья большие или если обновлений несколько подряд. И это очень серьезные проблемы. Настолько серьезные, что команда React потратила годы на улучшение ситуации. Но об этом — в следующем посте.

