Рука, касающаяся экрана смартфона

Оптимизация времени ожидания до первого взаимодействия с контентом

Оптимизация времени ожидания до первого взаимодействия с контентом

Как быстрее реагировать на взаимодействие с пользователем.

Appears in: Web Vitals

Я щелкнул, но ничего не произошло! Почему я не могу взаимодействовать с этой страницей? 😢

FCP (Первая отрисовка контента) и LCP (Скорость загрузки основного контента)это метрики, которые измеряют время, необходимое контенту для визуального отображения (отрисовки) на странице. Время отрисовки важно, но оно не отражает отзывчивость при загрузке, то есть то, как быстро страница реагирует на взаимодействие с пользователем.

FID (Время ожидания до первого взаимодействия с контентом)это метрика Core Web Vitals, которая фиксирует первое впечатление пользователя об интерактивности и быстродействии сайта. Она измеряет время от момента, когда пользователь впервые взаимодействует со страницей, до момента, когда браузер действительно может ответить на это взаимодействие. FIDполевая метрика, которую нельзя смоделировать в лабораторных условиях. Для измерения задержки ответа требуется взаимодействие с реальным пользователем.

Хорошие значения fid - 2,5 секунды, низкие значения больше 4,0 секунд, и все, что находится между ними, требует улучшения

Чтобы помочь предсказать FID в лабораторных условиях, мы рекомендуем использовать метрику TBT (Общее время блокировки). Хотя эти метрики не идентичны, но улучшение TBT обычно приводит к улучшению FID.

Основная причина плохого значения FID**«тяжелое» выполнение JavaScript**. Оптимизация анализа, компиляции и выполнения JavaScript на странице напрямую снижает FID.

«Тяжелое» выполнение JavaScript #

Браузер не может реагировать на большую часть пользовательского ввода, пока он выполняет JavaScript в основном потоке. Другими словами, браузер не может реагировать на действия пользователя, пока основной поток занят. Чтобы оптимизировать выполнение JavaScript:

Разделение длительных задач #

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

Длительные задачиэто периоды выполнения JavaScript, когда пользователи могут заметить, что пользовательский интерфейс не отвечает. Любой фрагмент кода, который блокирует основной поток на 50 мс или более, можно рассматривать как длительную задачу. Длительные задачипризнак потенциального раздувания JavaScript-кода (загрузка и выполнение большего количества задач, чем может потребоваться пользователю прямо сейчас). Разделение длительных задач может уменьшить задержку ввода на сайте.

Длительные задачи в Chrome DevTools
Chrome DevTools визуализирует длительные задачи на панели производительности

Значение FID должно заметно улучшиться при внедрении передовых практик, таких как разделение кода и разделение длительных задач. Хотя TBTэто не полевая метрика, но с ее помощью удобно отслеживать ход оптимизации метрик TTI (Время до интерактивности) и FID.

Для получения дополнительной информации прочтите статью «Увеличивают ли длительные задачи JavaScript время до интерактивности (TTI)?».

Оптимизация страницы для готовности к взаимодействию #

Существует ряд распространенных причин плохих оценок FID и TBT в веб-приложениях, которые в значительной степени зависят от JavaScript:

Выполнение основного скрипта может задержать готовность к взаимодействию #

  • Раздутие размера JavaScript-кода, большое время выполнения и неэффективное разбиение на фрагменты могут замедлить реакцию страницы на ввод пользователя и повлиять на FID, TBT и TTI. Постепенная загрузка кода и функций поможет распределить эту работу и повысить готовность к взаимодействию.
  • Приложения с рендерингом на стороне сервера могут выглядеть так, как будто они быстро рисуют пиксели на экране, но помните о том, что из-за выполнения большого количества скриптов взаимодействие с пользователем будет заблокировано (например, во время регидратации для подключения слушателей событий). Это может занять несколько сотен миллисекунд, или даже секунд, если используется разбиение кода на основе маршрута. Подумайте о том, чтобы перенести больше логики на сторону сервера или генерировать больше статического контента на этапе сборки.

Ниже приведены оценки TBT до и после оптимизации загрузки основных скриптов для приложения. После того как с критического этапа рендеринга была убрана ресурсоёмкая загрузка (и выполнение) скрипта для непервостепенного компонента, пользователи смогли гораздо быстрее взаимодействовать со страницей.

Улучшение показателя TBT в Lighthouse после оптимизации основного скрипта

Выборка данных может повлиять на многие аспекты готовности к взаимодействию #

  • Ожидание большого числа каскадных выборок (например, JavaScript и выборки данных для компонентов) может повлиять на задержку взаимодействия. Стремитесь свести к минимуму зависимость от каскадных выборок данных.
  • Большие локальные хранилища данных могут увеличить время синтаксического анализа HTML и повлиять на показатели отрисовки и взаимодействия. Стремитесь минимизировать объем данных, которые необходимо обрабатывать на стороне клиента.

Выполнение сторонних скриптов также может привести к задержке взаимодействия #

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

Использование веб-воркеров #

Заблокированный основной потокодна из главных причин задержки ввода. Веб-воркеры позволяют запускать JavaScript в фоновом потоке. Перенос операций, не связанных с пользовательским интерфейсом, в отдельный рабочий поток может сократить время блокировки основного потока и, следовательно, улучшить FID.

Подумайте о применении следующих библиотек, чтобы упростить использование веб-воркеров на сайте:

  • Comlink: вспомогательная библиотека, которая абстрагирует postMessage и упрощает работу с этим API.
  • Workway: универсальный экспортер веб-воркеров.
  • Workerize: служит для переноса модуля в веб-воркер.

Чтобы узнать больше о том, как веб-воркеры могут выполнять код вне основного потока, см. статью «Использование веб-воркеров для запуска JavaScript вне основного потока браузера».

Уменьшение времени выполнения JavaScript #

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

Чтобы уменьшить количество JavaScript, выполняемого на странице:

  • отложите загрузку неиспользуемого JavaScript;
  • минимизируйте неиспользуемые полифиллы.

Отсрочка загрузки неиспользуемого JavaScript #

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

На вкладке Coverage в Chrome DevTools можно узнать, сколько неиспользуемого кода JavaScript находится на вашей странице.

Вкладка Coverage.

Чтобы сократить неиспользуемый JavaScript:

  • разделите пакет на несколько частей;
  • отложите любой некритический JavaScript, включая сторонние скрипты, используя атрибут async или defer.

Разделение кодаэто концепция разделения одного большого пакета JavaScript на более мелкие фрагменты кода, которые загружаются по условию (отложенная загрузка). Большинство новых браузеров поддерживают синтаксис динамического импорта, который позволяет получать модуль по запросу:

import('module.js').then((module) => {
// Do something with the module.
});

Динамический импорт JavaScript при определенных взаимодействиях с пользователем (например, при изменении маршрута или отображении модального окна) гарантирует, что код, не используемый для начальной загрузки страницы, будет извлекаться только при необходимости.

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

  • Если вы применяете webpack, Rollup или Parcel в качестве сборщика модулей, воспользуйтесь их поддержкой динамического импорта.
  • Клиентские фреймворки, такие как React, Angular и Vue, предоставляют абстракции, упрощающие отложенную загрузку на уровне компонентов.

Ознакомьтесь со статьей «Сокращение полезной нагрузки JavaScript с помощью разделения кода», чтобы узнать больше о разделении кода.

Помимо разделения кода, всегда используйте атрибуты async или defer для скриптов, которые не нужны для критического этапа рендеринга или контента, видимого без прокрутки.

<script defer src=""></script>
<script async src=""></script>

Если нет особой причины не делать этого, все сторонние скрипты по умолчанию следует загружать с атрибутами defer либо async.

Минимизация неиспользуемых полифиллов #

Если вы пишете свой код с использованием современного синтаксиса JavaScript и ссылаетесь на API современных браузеров, вам потребуется транспилировать код и включить полифиллы, чтобы код работал и в старых браузерах.

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

Чтобы оптимизировать использование полифиллов на сайте:

  • Если в качестве транспилятора вы применяете Babel, используйте модуль @babel/preset-env, чтобы включить только полифиллы, необходимые для браузеров, на которые вы планируете настроить таргетинг. Для Babel 7.9 включите опцию bugfixes, чтобы ещё больше сократить количество ненужных полифиллов.

  • Используйте шаблон module/nomodule для доставки двух отдельных пакетов (модуль @babel/preset-env также поддерживает эту функцию через target.esmodules).

    <script type="module" src="modern.js"></script>
    <script nomodule src="legacy.js" defer></script>

    Многие новые функции ECMAScript, скомпилированные с помощью Babel, уже поддерживаются в средах, поддерживающих модули JavaScript. Таким образом, теперь проще отследить, чтобы транспилированный код применялся только для браузеров, которые действительно в нём нуждаются.

В статье «Современным браузерамсовременный код для ускорения загрузки страниц» более подробно рассматривается эта тема.

Инструменты разработчика #

Для измерения и отладки FID доступен ряд инструментов:

  • Lighthouse 6.0 не поддерживает FID, поскольку это полевой показатель. Однако метрику TBT (Общее время блокировки) можно использовать в качестве косвенного показателя. Оптимизация, улучшающая TBT, должна также улучшить FID в полевых условиях.

    Lighthouse 6.0.
  • Отчет Chrome User Experience Report предоставляет реальные значения FID, агрегированные на уровне источника.

Выражаем благодарность Филиппу Уолтону, Кейси Баскесу, Илье Григорику и Энни Салливан за их обзоры.

Last updated: Improve article