Как стать автором
Поиск
Написать публикацию
Обновить

Комментарии 24

Браузер не инициирует лишнюю перерисовку страницы если обращения к DOM API происходят в коде синхронно. "Точечные изменения", которые делают за вас библиотеки - именно так и работают. Из этого следует, что взаимодействовать с DOM напрямую - это вовсе не плохая идея, а напротив, путь к более эффективным решениям. Подтверждением этому является множество современных библиотек, отказавшихся от концепции Virtual DOM. В общем, неплохая статья, где-то до середины.

Браузер не инициирует лишнюю перерисовку страницы если обращения к DOM API происходят в коде синхронно.

Дьявол кроется в деталях — действительно на экране ничего не изменится. А вот вызвать reflow (который может быть весьма вычислительно тяжелым, в зависимости от DOM) в синхронном коде — не особо сложно даже в современнейших браузерах (которые сами по себе сильно оптимизируют reflow/repaint, когда могут).

не особо сложно

Как? Приведите пример.

Поменять что-то в элементе и тут же спросить у него, например, offsetHeight. Вроде ещё недавно такое приводило к рефлоу, хотя может быть сейчас оптимизировали и это.

Хороший пример. Показывает, что получение результатов вычисления требует этих самых вычислений, независимо от степени оптимизации. Ну, то есть, если специально запрашивать рефлоу и он произойдет - то это ожидаемое поведение. Я же говорю о ЛИШНИХ перерисовках, которые никак не оптимизируются на уровне синхронизации с Virtual DOM, потому как при этой синхронизации используется тот-же самый синхронный вызов методов DOM API.

Тут есть такой момент - меняем мы один элемент, а потом спрашиваем что-то от другого. При этом часто нам нужно именно прошлое значение свойства, а не пересчитанное с учётом изменения другого элемента. Грубо говоря, в идеале рендер должен происходить так: сначала прочитали из дома всё, что нам нужно, потом обновили дом с учётом прочитанного. Но это не масштабируется. Когда мы разбиваем на компоненты, каждый из них начинает читать и писать вперемешку, что приводит к лишним пересчётам и неожиданным результатам. Тут бы иметь какую-то форму версионирования или откладывания фактических изменений до завершения рендера.VDOM с эти конечно худо-бедно справляется, но цена за это непомерная. IDOM в этом свете выглядит гораздо лучше.

Библиотека https://github.com/wilsonpage/fastdom в принципе позволяет такое сделать и при разбиении на компоненты: все вызовы чтения/изменения DOM в компонентах надо делать через fastdom.measure() и fastdom.mutate() , а библиотека сама их сгруппирует.

Я же говорю о ЛИШНИХ перерисовках, которые никак не оптимизируются на уровне синхронизации с Virtual DOM, потому как при этой синхронизации используется тот-же самый синхронный вызов методов DOM API.

Ну так это всё никак не регулируется спецификациями — это на самом деле чисто browser-specific поведение, что, например, тот же хром не будет делать лишних движений, если может обойтись без reflow. А какой-нибудь старый или просто местячковый браузер — вполне может.


Но, разумеется, общего неправильного посыла статьи это не меняет, потому что как ниже правильно заметили, vdom — он про сохранение привычных абстракций, а не про оптимизацию быстродействия. В конце концов, никто за десятилетия не выкатил разгромных бенчмарков, в которых реакт бы рвал всех по производительности. Совсем наоборот, когда ты ангулярщикам рассказываешь про то, что в реакте лишний раз render() страшно дернуть (много возни с vdom и легко получить брутальный performance hit на ровном месте в некоторых не особо экзотичных обстоятельствах), они на тебя смотрят немного с жалостью.

А потом Ангулящикам показываешь, как одно пролетающее в стороне событие вызывает пересчёт всех компонент приложения, и они уже с грустью смотрят на необходимость переводить все компоненты с автоматического трекинга изменений на ручной.

Про сохранение абстракций — хорошая формулировка, согласен (если добавить к ней «в том числе и...»). Но общий посыл не о том, что VDOM позволяет оптимизировать быстродействие, и не про сам VDOM как таковой. А про то, как вообще с изменением подходов и задач развивалось взаимодействие с DOM. Как решения, дававшие плюсы при одном подходе, оказывались минусами при другом, и это приводило к следующей итерации. Как и в любой статье — что-то упрощено, да. Это неизбежно, ведь и весь путь изменений в работе с DOM не был «предначертан заранее», это результат многих итераций, чтобы получить искомое. Текущее состояние тоже не финал, что-то да придет на смену.

Сравнение на примере точечного изменения тоже не совсем корректно, да и сейчас, как совершенно верно замечено, подход меняется.

НЛО прилетело и опубликовало эту надпись здесь

Мда, столько костылей и библиотек, только для того, чтобы обойти суровую особенность DOM

которой нет

НЛО прилетело и опубликовало эту надпись здесь

Хотите сказать что Virtual DOM чудесным образом уменьшает это все при добавлении одной ноды в дерево?

Я открывал профилировщик и сравнивал React с одной мало известной библиотекой - результат время на рендеринг без изменений, процессор и память в разы больше утилизируются при использовании Virtual DOM

Хотите сказать что Virtual DOM чудесным образом уменьшает это все при добавлении одной ноды в дерево?

Когда говорят что virtual-dom очень быстрый, то обычно сравнивают какое-нибудь точечное изменение в DOM, с заменой какого-нибудь большого узла целиком. Аргументируют это тем. что за счёт vDom и реконсиляции библиотека знает что поменять, а ваше %frameworkname% нет и патчит всё по хардкору.


И откровенно говоря, в те времена когда появился React это было более-менее правдиво. Много SPA тех времён и правда нещадно экплуатировали innerHTML, потому что это было просто. Прогнал новые данные по функции-шаблону, получил кусок HTML, заменил старый на новый. По пути потерял весь state вроде позиции скролла, курсор, :focus и пр…


Сейчас это уже совсем не так, и все популярные решения стараются бить по DOM как можно более точечно. Например, если используется observable, то можно сделать автоматически отдельную подписку на нужные значения, от которых зависит какой-нибудь attribute. Ну и разница выходит в BigO, который очень разный. Где-то идёт зависимость от числа задействованных реактивных элементов, а где-то от числа нод на сравнение с прошлым слепком.

НЛО прилетело и опубликовало эту надпись здесь
  1. Не будет оно каждый раз перерендериваться. Браузеры не совсем дураки разрабатывают.

  2. Попробуйте в Реакте перенести жирный кусок VDOM из одного родителя в другой - он перерендерит всё с нуля вместо 1 операции с DOM.

Вот интересно. А есть решения где п2 как-то иначе сработает? Имею ввиду автоматику, не вручную. Наверное для этого нужна некая глобальная идентификация таких звеньев. $mol?

Ну да, нужны гуиды не привязанные к положению как в $mol.

Virtual DOM был придуман не для оптимизации перерисовки, а для того чтобы натянуть сову на глобус - заменить innerHTML и продолжать генерить страницы как привыкли.

Эх, жаль не могу голосовать, Ваш ответ вот самый-самый в точку?

А я могу поставить плюс и поставлю?, только немного переформулирую — не только для оптимизации, но и для сохранения привычных абстракций (как сказали выше в комментах). Одно другому не противоречит.

Angular — единственный фреймворк большой тройки, изначально построенный на архитектуре с использованием template, когда все компоненты пишутся с использованием шаблонов

Я бы сказал, что React (с его клонами) - чуть ли не единственный, где не "используются template".

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации