Еще больше интересного в нашем телеграм канале - @frontend_campus
Большие размеры DOM влияют на интерактивность больше, чем вы думаете. Это руководство объясняет, почему это происходит и что вы можете сделать с этим.
Без этого не обойтись: когда вы создаете веб-страницу, она будет иметь объектную модель документа (DOM). DOM представляет собой структуру HTML вашей страницы и дает JavaScript и CSS доступ к структуре и содержимому страницы.
Проблема, однако, заключается в том, что размер DOM влияет на способность браузера быстро и эффективно отображать страницу. Вообще говоря, чем больше DOM, тем дороже обходится первоначальная визуализация страницы и обновление ее визуализации на более поздних этапах жизненного цикла страницы.
Это становится проблематичным на страницах с очень большим DOM, когда взаимодействия, изменяющие или обновляющие DOM, вызывают дорогостоящую работу по компоновке, которая влияет на способность страницы быстро реагировать. Дорогостоящая работа по компоновке может повлиять на показатель "Взаимодействие до следующей отрисовки" (INP) страницы; если вы хотите, чтобы страница быстро реагировала на взаимодействие с пользователем, важно убедиться, что размеры DOM настолько велики, насколько это необходимо.
Когда DOM страницы слишком велик?
Ключевой термин
Важно знать разницу между элементами DOM и узлами DOM. Элемент DOM относится к определенному элементу HTML в дереве DOM. Узел DOM имеет пересекающееся значение с термином элемент DOM, но его определение расширено и включает комментарии, пробельные символы и текст. Хотя аудит размера DOM в Lighthouse относится к узлам DOM, в данном руководстве по возможности будут использоваться элементы DOM, а не узлы.
Согласно Lighthouse, размер DOM страницы является чрезмерным, если он превышает 1 400 узлов. Lighthouse начнет выдавать предупреждения, когда DOM страницы превысит 800 узлов. Возьмем для примера следующий HTML:
<ul>
<li>List item one.</li>
<li>List item two.</li>
<li>List item three.</li>
</ul>
В приведенном выше коде есть четыре элемента DOM: элемент <ul> и три его дочерних элемента <li>. Ваша веб-страница почти наверняка будет содержать гораздо больше узлов, чем это, поэтому важно понимать, что можно сделать, чтобы держать размеры DOM под контролем - а также другие стратегии для оптимизации работы рендеринга после того, как вы сделали DOM страницы настолько маленьким, насколько это возможно.
Как большие DOM влияют на производительность страницы?
Большие DOM влияют на производительность страницы несколькими способами:
- Во время первоначального рендеринга страницы. Когда CSS применяется к странице, создается структура, похожая на DOM, известная как CSS Object Model (CSSOM). По мере увеличения специфичности селекторов CSS, CSSOM становится все сложнее, и требуется больше времени для выполнения необходимых операций по компоновке, стилизации, композитингу и рисованию, необходимых для вывода веб-страницы на экран. Эта дополнительная работа увеличивает задержку при взаимодействии, которое происходит на ранних стадиях загрузки страницы.
- Когда взаимодействие изменяет DOM, либо путем вставки или удаления элементов, либо путем изменения содержимого DOM и стилей, работа, необходимая для рендеринга этого обновления, может привести к очень дорогостоящей работе по компоновке, стилизации, композитингу и рисованию. Как и в случае с первоначальным рендерингом страницы, увеличение специфичности селекторов CSS может увеличить объем работы по рендерингу, когда элементы HTML вставляются в DOM в результате взаимодействия.
- Когда JavaScript запрашивает DOM, ссылки на элементы DOM хранятся в памяти. Например, если вы вызываете document.querySelectorAll запрос на выборку всех элементов <div> на странице, затраты памяти могут быть значительными, если результат возвращает большое количество элементов DOM.
Все это может повлиять на интерактивность, но второй пункт в приведенном выше списке имеет особое значение. Если взаимодействие приводит к изменению DOM, это может запустить много работы, которая может способствовать плохому INP на странице.
Как измерить размер DOM?
Размер DOM можно измерить несколькими способами. Первый способ использует Lighthouse. Когда вы запускаете аудит, статистика по DOM текущей страницы будет находиться в разделе "Избежать чрезмерного размера DOM" под заголовком "Диагностика". В этом разделе можно увидеть общее количество элементов DOM, элемент DOM, содержащий наибольшее количество дочерних элементов, а также самый глубокий элемент DOM.
Более простой метод предполагает использование консоли JavaScript в инструментах разработчика в любом основном браузере. Чтобы получить общее количество элементов HTML в DOM, вы можете использовать следующий код в консоли после загрузки страницы:
document.querySelectorAll('*').length;
Если вы хотите видеть обновление размера DOM в реальном времени, вы также можете использовать инструмент монитора производительности. Используя этот инструмент, вы можете соотнести операции компоновки и стилизации (и другие аспекты производительности) с текущим размером DOM.
Если размер DOM приближается к порогу предупреждения Lighthouse, следующим шагом будет выяснение того, как уменьшить размер DOM, чтобы улучшить способность страницы реагировать на взаимодействие с пользователем, чтобы улучшить INP вашего сайта.
Как измерить количество элементов DOM, затронутых взаимодействием?
Если вы профилируете медленное взаимодействие в лаборатории, которое, как вы подозреваете, может быть как-то связано с размером DOM страницы, вы можете выяснить, сколько элементов DOM было затронуто, выбрав любой фрагмент активности в профилировщике с надписью "Recalculate Style" и наблюдая за контекстными данными в нижней панели.
На скриншоте выше обратите внимание, что пересчет стиля работы - при выборе - показывает количество затронутых элементов. Хотя приведенный выше скриншот показывает крайний случай влияния размера DOM на работу рендеринга на странице с большим количеством элементов DOM, эта диагностическая информация полезна в любом случае, чтобы определить, является ли размер DOM ограничивающим фактором в том, сколько времени требуется для отрисовки следующего кадра в ответ на взаимодействие.
Как уменьшить размер DOM?
Помимо проверки HTML вашего сайта на наличие ненужной разметки, основным способом уменьшения размера DOM является уменьшение глубины DOM. Одним из сигналов того, что ваш DOM может быть излишне глубоким, является появление разметки, которая выглядит примерно так на вкладке "Элементы" в инструментах разработчика вашего браузера:
<div>
<div>
<div>
<div>
<!-- Contents -->
</div>
</div>
</div>
</div>
Когда вы видите подобные шаблоны, вы, вероятно, можете упростить их, упростив структуру DOM. Это уменьшит количество элементов DOM и, вероятно, даст вам возможность упростить стили страницы.
Глубина DOM также может быть симптомом используемых вами фреймворков. В частности, компонентные фреймворки, такие как те, которые основаны на JSX, требуют вложения нескольких компонентов в родительский контейнер.
Однако многие фреймворки позволяют избежать вложения компонентов, используя так называемые фрагменты. Фреймворки на основе компонентов, которые предлагают фрагменты в качестве функции, включают (но не ограничиваются) следующие:
React
Preact
Vue
Svelte
Используя фрагменты в выбранном вами фреймворке, вы можете уменьшить глубину DOM. Если вас беспокоит влияние уплощения структуры DOM на стилизацию, вам может быть полезно использовать более современные (и более быстрые) режимы компоновки, такие как flexbox или grid.
Другие стратегии для рассмотрения
Даже если вы постараетесь сгладить дерево DOM и удалить ненужные элементы HTML, чтобы сделать DOM как можно меньше, он все равно может быть довольно большим и вызывать много работы по рендерингу, поскольку изменяется в ответ на действия пользователя. Если вы оказались в таком положении, есть несколько других стратегий, которые можно рассмотреть для ограничения работы рендеринга.
Рассмотрите аддитивный подход
Вы можете оказаться в ситуации, когда большие части вашей страницы изначально не видны пользователю при первом отображении. Это может быть возможностью ленивой загрузки HTML, опуская эти части DOM при запуске, но добавляя их, когда пользователь взаимодействует с теми частями страницы, которые требуют первоначально скрытых аспектов страницы.
Этот подход полезен как во время начальной загрузки, так и, возможно, после нее. При первоначальной загрузке страницы вы берете на себя меньше работы по рендерингу, что означает, что ваш первоначальный HTML будет легче и будет рендериться быстрее. Это даст взаимодействиям в этот критический период больше возможностей для выполнения с меньшей конкуренцией за внимание основного потока.
Если у вас много частей страницы, которые изначально скрываются при загрузке, это также может ускорить другие взаимодействия, которые вызывают повторную визуализацию. Однако по мере того, как другие взаимодействия добавляют все больше информации в DOM, работа по рендерингу будет увеличиваться по мере роста DOM в течение жизненного цикла страницы.
Добавление в DOM с течением времени может быть сложным, и это имеет свои собственные компромиссы. Если вы идете по этому пути, вы, скорее всего, делаете сетевые запросы для получения данных, чтобы заполнить HTML, который вы собираетесь добавить на страницу в ответ на взаимодействие с пользователем. Хотя сетевые запросы в полете не учитываются в INP, они могут увеличить воспринимаемую задержку. Если возможно, покажите загрузку или другой индикатор того, что данные подхватываются, чтобы пользователи понимали, что что-то происходит.
Ограничьте сложность селекторов CSS
Когда браузер анализирует селекторы в вашем CSS, он должен пройти по дереву DOM, чтобы понять, как и если эти селекторы применяются к текущему макету. Чем сложнее эти селекторы, тем больше работы приходится выполнять браузеру для первоначального рендеринга страницы, а также для пересчета стилей и верстки, если страница меняется в результате взаимодействия.
Используйте свойство content-visibility
CSS предлагает свойство content-visibility, которое фактически является способом ленивого отображения элементов DOM вне экрана. Когда элементы приближаются к области просмотра, они отображаются по требованию. Преимущества свойства content-visibility заключаются не только в сокращении значительного объема работы по рендерингу при первоначальном рендеринге страницы, но и в пропуске работы по рендерингу для внеэкранных элементов, когда DOM страницы изменяется в результате взаимодействия с пользователем.
Заключение
Уменьшение размера DOM до строго необходимого - хороший способ оптимизации INP вашего сайта. Таким образом, вы можете уменьшить количество времени, которое требуется браузеру для выполнения работ по верстке и рендерингу при обновлении DOM. Даже если вы не можете значительно уменьшить размер DOM, есть некоторые методы, которые можно использовать для изоляции работы по рендерингу в поддереве DOM, такие как CSS containment и CSS-свойство content-visibility.
Как бы вы ни поступили, создавая среду, в которой работа по рендерингу сведена к минимуму, а также уменьшая количество работы по рендерингу, которую выполняет ваша страница в ответ на взаимодействие, в результате ваш сайт будет более отзывчивым к пользователям, когда они взаимодействуют с ним. Это означает, что у вас будет более низкий INP для вашего сайта, а это означает более высокий уровень пользовательского опыта.
Еще больше интересного в нашем телеграм канале - @frontend_campus