Как большие размеры DOM влияют на интерактивность и что с этим можно сделать

Большие размеры DOM оказывают большее влияние на интерактивность, чем вы думаете. В этом руководстве объясняется, почему и что вы можете сделать.

Обойти это невозможно: когда вы создаете веб-страницу, эта страница будет иметь объектную модель документа (DOM) . DOM представляет структуру HTML вашей страницы и предоставляет JavaScript и CSS доступ к структуре и содержимому страницы.

Проблема, однако, в том, что размер DOM влияет на способность браузера быстро и эффективно отображать страницу. Вообще говоря, чем больше DOM, тем дороже первоначально отрисовывать эту страницу и обновлять ее отрисовку на более позднем этапе жизненного цикла страницы.

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

Когда DOM страницы слишком велик?

По данным Lighthouse , размер DOM страницы является чрезмерным, если он превышает 1400 узлов. 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 влияют на производительность страницы несколькими способами:

  1. Во время первоначального рендеринга страницы. Когда CSS применяется к странице, создается структура, похожая на DOM, известная как объектная модель CSS (CSSOM) . По мере того, как селекторы CSS становятся все более специфичными, CSSOM становится более сложным, и требуется больше времени для выполнения необходимых работ по макетированию, стилизации, компоновке и рисованию, необходимых для отображения веб-страницы на экране. Эта дополнительная работа увеличивает задержку взаимодействия для взаимодействий, которые происходят на ранних этапах загрузки страницы.
  2. Когда взаимодействия изменяют DOM, либо путем вставки или удаления элемента, либо путем изменения содержимого и стилей DOM, работа, необходимая для рендеринга этого обновления, может привести к очень дорогостоящим работам по макетированию, стилизации, композиции и покраске. Как и в случае с первоначальным рендерингом страницы, повышение специфичности селектора CSS может добавить к работе рендеринга, когда HTML-элементы вставляются в DOM в результате взаимодействия.
  3. Когда JavaScript запрашивает DOM, ссылки на элементы DOM сохраняются в памяти. Например, если вы вызываете document.querySelectorAll для выбора всех элементов <div> на странице, затраты памяти могут быть значительными, если результат возвращает большое количество элементов DOM.
Скриншот длинной задачи, вызванной чрезмерной работой рендеринга на панели производительности Chrome DevTools. Стек вызовов длинной задачи показывает, что значительное время затрачивается на пересчет стилей страницы, а также на предварительную прорисовку.
Длинная задача, как показано в профилировщике производительности в Chrome DevTools. Показанная длинная задача вызвана вставкой элементов DOM в большой DOM с помощью JavaScript.

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

Как измерить размер DOM?

Вы можете измерить размер DOM несколькими способами. Первый метод использует Lighthouse. При запуске аудита статистика по DOM текущей страницы будет находиться в аудите «Избегайте чрезмерного размера DOM» под заголовком «Диагностика». В этом разделе вы можете увидеть общее количество элементов DOM, элемент DOM, содержащий наибольшее количество дочерних элементов, а также самый глубокий элемент DOM.

Более простой метод предполагает использование консоли JavaScript в инструментах разработчика любого крупного браузера. Чтобы получить общее количество HTML-элементов в DOM, вы можете использовать следующий код в консоли после загрузки страницы:

document.querySelectorAll('*').length;

Если вы хотите видеть обновление размера DOM в реальном времени, вы также можете использовать инструмент мониторинга производительности . Используя этот инструмент, вы можете сопоставить операции макета и стиля (и другие аспекты производительности) с текущим размером DOM.

Скриншот монитора производительности в Chrome DevTools. Слева показаны различные аспекты производительности страницы, которые можно постоянно отслеживать в течение всего срока службы страницы. На скриншоте активно отслеживается количество DOM-узлов, макетов в секунду и перерасчетов стилей на раздел.
Монитор производительности в Chrome DevTools. В этом представлении отображается текущее количество узлов DOM на странице, а также операции макета и перерасчеты стилей, выполняемые в секунду.

Если размер DOM приближается к порогу предупреждения размера Lighthouse DOM или вообще не работает, следующим шагом будет выяснить, как уменьшить размер DOM, чтобы улучшить способность вашей страницы реагировать на взаимодействия с пользователем и улучшить INP вашего веб-сайта.

Как я могу измерить количество элементов DOM, на которые влияет взаимодействие?

Если вы профилируете в лаборатории медленное взаимодействие, которое, как вы подозреваете, может иметь какое-то отношение к размеру DOM страницы, вы можете выяснить, сколько элементов DOM было затронуто, выбрав в профилировщике любую часть действия с надписью «Пересчитать стиль». " и просмотрите контекстные данные на нижней панели.

Снимок экрана с выбранным действием пересчета стилей на панели производительности Chrome DevTools. Вверху дорожка взаимодействий показывает взаимодействие по щелчку, и большая часть работы уходит на перерасчет стиля и предварительную покраску. В нижней части панели отображается более подробная информация о выбранном действии, в которой сообщается, что были затронуты 2547 элементов DOM.
Наблюдение за количеством затронутых элементов в DOM в результате пересчета стилей. Обратите внимание, что заштрихованная часть взаимодействия на дорожке взаимодействий представляет собой часть взаимодействия, длительность которой превышает 200 миллисекунд, что является назначенным «хорошим» порогом для INP .

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

Как уменьшить размер DOM?

Помимо проверки HTML вашего веб-сайта на наличие ненужной разметки, основным способом уменьшения размера DOM является уменьшение глубины DOM. Одним из сигналов того, что ваш DOM может быть излишне глубоким, является то, что вы видите разметку, которая выглядит примерно так, на вкладке «Элементы» инструментов разработчика вашего браузера:

<div>
  <div>
    <div>
      <div>
        <!-- Contents -->
      </div>
    </div>
  </div>
</div>

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

Глубина DOM также может быть признаком используемой вами платформы. В частности, платформы на основе компонентов, например те, которые полагаются на JSX , требуют вложения нескольких компонентов в родительский контейнер.

Однако многие платформы позволяют избежать вложения компонентов за счет использования так называемых фрагментов. Платформы на основе компонентов, которые предлагают фрагменты в качестве функции, включают (но не ограничиваются) следующее:

Используя фрагменты в выбранной вами среде, вы можете уменьшить глубину 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-включение и CSS-свойство content-visibility .

Как бы вы это ни делали, создавая среду, в которой работа по рендерингу сводится к минимуму, а также уменьшая объем работы по рендерингу, которую ваша страница выполняет в ответ на взаимодействия, в результате ваш веб-сайт будет более отзывчивым к пользователям, когда они с ними взаимодействуют. . Это означает, что у вас будет более низкий INP для вашего веб-сайта, а это приведет к улучшению пользовательского опыта.

Героическое изображение из Unsplash , автор Луис Рид .