Виртуальный DOM — одна из основных концепций, представленных React. Как фронтенд-инженер, важно понимать его внутренний рабочий процесс и проблемы с производительностью, которые React решает по сравнению с нативным JS. В этой статье мы углубимся в корень проблемы и метод, который предлагает React.

Рендеринг страницы

Напомним высокоуровневый обзор процесса рендеринга в браузере.

  • Во-первых, содержимое HTML и CSS передается в соответствующие синтаксические анализаторы для создания HTML DOM и CSSOM.
  • Во время процедуры присоединения HTML DOM и CSSOM затем объединяются в единое дерево рендеринга, содержащее только узлы, необходимые для рендеринга.
  • Шаг layout включает в себя вычисление ширины, высоты и координат элементов.
  • Процедура рисования включает добавление графики к элементам. На этом этапе у нас есть растровые представления элементов, которые должны отображаться на экране в определенном порядке.
  • Наконец, есть операция composite, которая отправляет построенные слои в GPU для отрисовки элементов на экране.

Для получения более подробной информации о рендеринге я настоятельно рекомендую ознакомиться с блестящим объяснением Райана Седдона:

Основываясь на информации, представленной в этом разделе, основные выводы заключаются в следующем:

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

Что происходит, когда вы обновляете DOM?

Помните, что модель DOM представлена ​​в виде древовидной структуры данных. Если вы измените существующий элемент или добавите новый, то изменения должны быть внесены и в предков элемента. В результате страницу необходимо отрисовать заново.

Одно из основных требований к современным веб-сайтам — возможность часто обновлять свой контент без перезагрузки страницы. В большинстве случаев выполнение нескольких таких обновлений не приводит к проблемам с производительностью.

Однако проблема возникает, когда нам нужно обработать сотни таких запросов за короткий промежуток времени. Обновление дерева DOM и повторного рендеринга пользовательского интерфейса с помощью vanilla JS может снизить производительность вашего приложения. Именно здесь в игру вступают React и Virtual DOM, которые предлагают другой подход.

Добро пожаловать, Виртуальный ДОМ!

React использует Virtual DOM, который является абстракцией над DOM. Он имеет аналогичную структуру, в которой хранятся те же узлы. Проблема с оригинальным DOM заключается в том, что в каждом узле слишком много полей, которые не используются во время операции обновления. В результате это замедляет процесс обновления.

Виртуальный DOM не содержит всех полей, как DOM, и намного легче. Благодаря своей структуре обновления в Virtual DOM более оптимизированы. Но чтобы использовать Virtual DOM для обновлений, нам сначала нужно построить DOM, что требует относительно много времени. Более того, изменения, внесенные в виртуальный DOM, в будущем придется перенести в исходный DOM, что является еще одной потерей времени. Где реальная прибыль?

Где сияет виртуальный DOM?

Было бы глупо использовать Virtual DOM описанным выше способом. Вместо этого React предлагает лучшее решение:

💡 Почему бы не использовать виртуальный DOM для одновременной последовательности обновлений вместо отдельных обновлений?

Представьте, что нам нужно выполнить 50 обновлений за короткий промежуток времени (например, за 1 секунду). Для этого мы создаем виртуальный DOM и сохраняем его копию. После этого выполняем все 50 обновлений в его структуре. Поскольку обновления в Virtual DOM происходят намного быстрее, чем в DOM, этот процесс не занимает много времени.

Благодаря простоте структуры Virtual DOM React реализует очень оптимизированный алгоритм, который может вычислить разницу между двумя виртуальными DOM. Этот процесс называется различением.

Быстро вычисляя разницу между первой версией Virtual DOM (после того, как она была первоначально построена) и последней версией (после всех обновлений), React берет эту разницу и применяет изменения к исходной модели DOM. Поскольку обновления выполняются одновременно, нет необходимости каждый раз перестраивать DOM. Это главное преимущество, которое значительно повышает производительность.

Нужно ли когда-нибудь использовать Vanilla JS?

Предположим, вы создаете статический веб-сайт, на котором происходят очень редкие события (средний промежуток времени между каждым событием велик). Если вы решите использовать для него React и Virtual DOM, то для каждого отдельного обновления вам придется строить виртуальный DOM, делать там обновление, вычислять разницу между двумя виртуальными DOM и только потом использовать эту разницу для обновления исходного DOM. Очевидно, что это избыточный процесс для одного обновления.

Напротив, выполнение одиночных обновлений с помощью собственного JS было бы намного быстрее, поскольку вам нужно только обновить и перестроить структуру DOM.

В результате нет однозначного ответа на вопрос, всегда ли использовать vanilla JS или React. Лучшее решение о том, использовать vanilla JS или React, во многом зависит от частоты событий, происходящих на веб-сайте. Vanilla JS лучше подходит для статических веб-сайтов, а React — для динамических.

💡 Еще одно преимущество React заключается в том, что вам как разработчику не нужно менять внутреннюю структуру DOM, занимаясь обходами DOM, манипулированием атрибутами или обработчиками событий. Все, что вам нужно сделать, это изменить состояния ваших компонентов, а React сделает остальную работу за вас.

Заключение

Мы рассмотрели объяснение основной проблемы, которую React призван решить. Понимание этих основных теоретических концепций необходимо, так как это облегчит понимание других принципов React.

Спасибо за чтение! 🚀