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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Помните о перекрытии взаимодействия

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

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

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

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

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

Заключение

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

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