DevGang
Авторизоваться

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

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

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

First Contentful Paint (FCP) и Largest Contentful Paint (LCP) - это метрики, которые измеряют время, необходимое для визуального отображения (рисования) контента на странице. Хотя это важно, время рисования не учитывает реакцию на нагрузку или то, как быстро страница реагирует на взаимодействие с пользователем.  

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

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

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

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

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

  • Сократить время выполнения JavaScript
  • Разбить длинные задачи
  • Оптимизировать свою страницу для обеспечения готовности к взаимодействию
  • Использовать веб-работника

Сократить время выполнения JavaScript

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

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

  • Сократить и сжать файлы JavaScript
  • Отложить неиспользуемый JavaScript
  • Минимизировать неиспользованные полифилы

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

Сократить и сжать файлы JavaScript

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

Terser поддерживает синтаксис ES6+ и может использоваться для минимизации современных файлов JavaScript без необходимости их транспилирования. Если вы используете связку модулей и хотите включить Terser в свою цепочку инструментов:

  • Webpack и Parcel уже минимизируют использование Terser по умолчанию в режиме production
  • Если вы используете Rollup, включите rollup-plugin-terser в качестве выходного плагина

В дополнение к минимизации, сжимайте ваши ресурсы JavaScript, чтобы минимизировать размер их доставки. Если возможно, используйте Brotli, который обеспечивает лучшие результаты сжатия, чем Gzip, и может использоваться практически во всех новых браузерах.

Отложить неиспользованный JavaScript

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

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

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

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

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

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

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

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

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

Помимо разделения кода, всегда используйте 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. Таким образом, делая это, вы упрощаете процесс проверки того, что только транспилированный код используется для браузеров, которые действительно нуждаются в нем.

Разбейте длинные задачи

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

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

Разделение длинных задач может уменьшить задержку ввода на вашем сайте.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. Comlink: вспомогательная библиотека, которая абстрагируется и облегчает использование postMessage
  2. Workway: экспортер веб-работника общего назначения
  3. Workerize: перемещение модуля в веб-работника

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

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

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

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

Источник:

#JavaScript
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

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

Попробовать

Сделайте первый шаг к новой профессии

Получить скидку