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

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

Взаимодействие в интернете — сложный процесс, в котором задействовано множество различных действий в браузере. Однако всех их объединяет одна особенность: перед началом обработки событий возникает некоторая задержка ввода. В этом руководстве вы узнаете, что такое задержка ввода и как её минимизировать, чтобы взаимодействие с вашим сайтом происходило быстрее.

Что такое задержка на входе?

Задержка ввода — это период времени, начинающийся с момента первого взаимодействия пользователя со страницей (например, касания экрана, щелчка мышью или нажатия клавиши) и заканчивающийся началом выполнения обработчиков событий для этого взаимодействия. Каждое взаимодействие начинается с некоторой задержки ввода.

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

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

Как понимать задержку ввода

В целом, желательно, чтобы каждый этап взаимодействия был как можно короче, чтобы у вашего веб-сайта были наилучшие шансы соответствовать пороговому значению «хорошо» по метрике «Взаимодействие до следующей отрисовки» (INP) , независимо от устройства пользователя. Контроль задержки ввода — это лишь один из способов достижения этого порога.

Следовательно, вам следует стремиться к минимально возможной задержке ввода, чтобы соответствовать «хорошему» порогу INP. Однако следует помнить, что полностью исключить задержки ввода невозможно. Пока вы избегаете чрезмерной нагрузки на основной поток во время взаимодействия пользователей с вашей страницей, задержка ввода должна быть достаточно низкой, чтобы избежать проблем.

Как минимизировать задержку ввода

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

Избегайте повторяющихся таймеров, которые запускают избыточную работу основного потока.

В JavaScript есть две часто используемые функции таймера, которые могут влиять на задержку ввода: setTimeout и setInterval . Разница между ними заключается в том, что setTimeout планирует выполнение функции обратного вызова через заданное время. setInterval , с другой стороны, планирует выполнение функции обратного вызова каждые n миллисекунд бесконечно или до тех пор, пока таймер не будет остановлен с помощью clearInterval .

setTimeout сам по себе не представляет проблемы — на самом деле, он может быть полезен для избежания длительных задач . Однако это зависит от того, когда происходит таймаут и пытается ли пользователь взаимодействовать со страницей в момент срабатывания функции обратного вызова по истечении таймаута.

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

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

Скриншот профилировщика производительности в инструментах разработчика Chrome, демонстрирующий задержку ввода. Задача, запускаемая функцией таймера, возникает непосредственно перед тем, как пользователь инициирует взаимодействие по клику. Однако таймер увеличивает задержку ввода, в результате чего события обратного вызова взаимодействия выполняются позже, чем это было бы в противном случае.
Таймер, зарегистрированный предыдущим вызовом setInterval вносит вклад в задержку ввода, как показано на панели производительности в инструментах разработчика Chrome. Дополнительная задержка ввода приводит к тому, что обратные вызовы событий для взаимодействия выполняются позже, чем могли бы.

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

Избегайте длительных задач.

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

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

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

Учитывайте возможное пересечение во взаимодействии.

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

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

Источники пересечения взаимодействий могут быть довольно простыми, например, когда пользователи совершают множество действий за короткий промежуток времени. Это может происходить, когда пользователи вводят текст в поля форм, где за очень короткий промежуток времени может произойти множество нажатий клавиш. Если обработка события нажатия клавиши особенно затратна — например, в распространенном случае полей автозаполнения, где отправляются сетевые запросы к бэкэнду — у вас есть несколько вариантов:

  • Рекомендуется использовать подавление дребезга входных сигналов, чтобы ограничить количество вызовов функции обратного вызова события за определенный период времени.
  • Используйте AbortController для отмены исходящих запросов fetch , чтобы основной поток не перегружался обработкой коллбэков fetch . Примечание: свойство signal экземпляра AbortController также можно использовать для отмены событий .

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

Заключение

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

Главное изображение взято с Unsplash , автор — Эрик Маклин .