---
title: Оптимизация времени ожидания до первого взаимодействия с контентом
subhead: Как быстрее реагировать на взаимодействие с пользователем.
authors:
  - houssein
  - addyosmani
date: 2020-05-05
updated: 2022-07-18
hero: image/admin/WH0KlcJXJlxvsxU9ow2i.jpg
alt: Рука, касающаяся экрана смартфона
description: Метрика FID (Время ожидания до первого взаимодействия с контентом) измеряет время с момента первого взаимодействия пользователя с сайтом до момента, когда браузер фактически способен ответить на это взаимодействие. Узнайте, как оптимизировать FID путем минимизации неиспользуемого JavaScript, разбиения длительных задач и улучшения готовности к взаимодействию.
tags:
  - blog
  - performance
  - web-vitals
---

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

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

[FID (Время ожидания до первого взаимодействия с контентом)](/fid/) — это [метрика Core Web Vitals](/vitals/), которая фиксирует первое впечатление пользователя об интерактивности и быстродействии сайта. Она измеряет время от момента, когда пользователь впервые взаимодействует со страницей, до момента, когда браузер действительно может ответить на это взаимодействие. FID — [полевая метрика](/user-centric-performance-metrics/#in-the-field), которую нельзя смоделировать в лабораторных условиях. Для измерения задержки ответа требуется **взаимодействие с реальным пользователем**.

  <picture>
    <source srcset="{{ "image/tcFciHGuF3MxnTr1y5ue01OGLBn2/eXyvkqRHQZ5iG38Axh1Z.svg" | imgix }}" media="(min-width: 640px)">
    {% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/Se4TiXIdp8jtLJVScWed.svg", alt="Хорошие значения fid - 2,5 секунды, низкие значения больше 4,0 секунд, и все, что находится между ними, требует улучшения", width="384", height="96" %}
  </picture>

Чтобы помочь предсказать FID в [лабораторных условиях](/how-to-measure-speed/#lab-data-vs-field-data), мы рекомендуем использовать метрику [TBT (Общее время блокировки)](/tbt/). Хотя эти метрики не идентичны, но улучшение TBT обычно приводит к улучшению FID.

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

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

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

- [разделите длительные задачи](#long-tasks);
- [оптимизируйте свою страницу, чтобы обеспечить готовность к взаимодействию](#optimize-interaction-readiness);
- [используйте веб-воркер](#use-a-web-worker);
- [уменьшите время выполнения JavaScript](#reduce-javascript-execution).

## Разделение длительных задач {: #long-tasks}

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

[**Длительные задачи**](/custom-metrics/#long-tasks-api) — это периоды выполнения JavaScript, когда пользователи могут заметить, что пользовательский интерфейс не отвечает. Любой фрагмент кода, который блокирует основной поток на 50 мс или более, можно рассматривать как длительную задачу. Длительные задачи — признак потенциального раздувания JavaScript-кода (загрузка и выполнение большего количества задач, чем может потребоваться пользователю прямо сейчас). Разделение длительных задач может уменьшить задержку ввода на сайте.

<figure>
  {% Img src="image/admin/THLKu0sOPhSghNr0XkP1.png", alt="Длительные задачи в Chrome DevTools", width="800", height="132" %}
  <figcaption> Chrome DevTools <a href="https://developers.google.com/web/updates/2020/03/devtools#long-tasks">визуализирует длительные задачи</a> на панели производительности</figcaption>
</figure>

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

{% Aside %} Для получения дополнительной информации прочтите статью [«Увеличивают ли длительные задачи JavaScript время до интерактивности (TTI)?»](/long-tasks-devtools/). {% endAside %}

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

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

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

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

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

{% Img src="image/tcFciHGuF3MxnTr1y5ue01OGLBn2/TEIbBnIAyfzIoQtvXvMk.png", alt="Улучшение показателя TBT в Lighthouse после оптимизации основного скрипта", width="800", height="148" %}

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

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

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

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

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

Заблокированный основной поток — одна из главных причин задержки ввода. [Веб-воркеры](https://developer.mozilla.org/docs/Web/API/Worker) позволяют запускать JavaScript в фоновом потоке. Перенос операций, не связанных с пользовательским интерфейсом, в отдельный рабочий поток может сократить время блокировки основного потока и, следовательно, улучшить FID.

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

- [Comlink](https://github.com/GoogleChromeLabs/comlink): вспомогательная библиотека, которая абстрагирует `postMessage` и упрощает работу с этим API.
- [Workway](https://github.com/WebReflection/workway): универсальный экспортер веб-воркеров.
- [Workerize](https://github.com/developit/workerize): служит для переноса модуля в веб-воркер.

{% Aside %} Чтобы узнать больше о том, как веб-воркеры могут выполнять код вне основного потока, см. статью [«Использование веб-воркеров для запуска JavaScript вне основного потока браузера»](/off-main-thread/). {% endAside %}

### Уменьшение времени выполнения JavaScript {: #reduce-javascript-execution}

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

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

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

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

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

На вкладке [Coverage](https://developer.chrome.com/docs/devtools/coverage/) в Chrome DevTools можно узнать, сколько неиспользуемого кода JavaScript находится на вашей странице.

{% Img src="image/admin/UNEigFiwsGu48rtXMZM4.png", alt="Вкладка Coverage.", width="800", height="559" %}

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

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

**Разделение кода** — это концепция разделения одного большого пакета JavaScript на более мелкие фрагменты кода, которые загружаются по условию (отложенная загрузка). [Большинство новых браузеров поддерживают синтаксис динамического импорта](https://caniuse.com/#feat=es6-module-dynamic-import), который позволяет получать модуль по запросу:

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

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

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

- Если вы применяете [webpack](https://webpack.js.org/guides/code-splitting/), [Rollup](https://medium.com/rollup/rollup-now-has-code-splitting-and-we-need-your-help-46defd901c82) или [Parcel](https://parceljs.org/code_splitting.html) в качестве сборщика модулей, воспользуйтесь их поддержкой динамического импорта.
- Клиентские фреймворки, такие как [React](https://reactjs.org/docs/code-splitting.html#reactlazy), [Angular](https://angular.io/guide/lazy-loading-ngmodules) и [Vue,](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components) предоставляют абстракции, упрощающие отложенную загрузку на уровне компонентов.

{% Aside %} Ознакомьтесь со статьей [«Сокращение полезной нагрузки JavaScript с помощью разделения кода»](/reduce-javascript-payloads-with-code-splitting/), чтобы узнать больше о разделении кода. {% endAside %}

Помимо разделения кода, всегда используйте атрибуты [async или defer](https://javascript.info/script-async-defer) для скриптов, которые не нужны для критического этапа рендеринга или контента, видимого без прокрутки.

```html
<script defer src="…"></script>
<script async src="…"></script>
```

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

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

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

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

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

- Если в качестве транспилятора вы применяете [Babel](https://babeljs.io/docs/en/index.html), используйте модуль [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env), чтобы включить только полифиллы, необходимые для браузеров, на которые вы планируете настроить таргетинг. Для Babel 7.9 включите опцию [`bugfixes`](https://babeljs.io/docs/en/babel-preset-env#bugfixes), чтобы ещё больше сократить количество ненужных полифиллов.

- Используйте шаблон module/nomodule для доставки двух отдельных пакетов (модуль `@babel/preset-env` также поддерживает эту функцию через [`target.esmodules`](https://babeljs.io/docs/en/babel-preset-env#targetsesmodules)).

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

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

{% Aside %} В статье [«Современным браузерам — современный код для ускорения загрузки страниц»](/serve-modern-code-to-modern-browsers/) более подробно рассматривается эта тема. {% endAside %}

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

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

- [Lighthouse 6.0](https://developer.chrome.com/docs/lighthouse/overview/) не поддерживает FID, поскольку это полевой показатель. Однако метрику [TBT (Общее время блокировки)](/tbt/) можно использовать в качестве косвенного показателя. Оптимизация, улучшающая TBT, должна также улучшить FID в полевых условиях.

    {% Img src="image/admin/FRM9kHWmsDv9dddGMgwu.jpg", alt="Lighthouse 6.0.", width="800", height="309" %}

- Отчет [Chrome User Experience Report](https://developer.chrome.com/docs/crux/) предоставляет реальные значения FID, агрегированные на уровне источника.

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