Оптимизация INP: как снизить влияние тяжелых
Сергей и ЛеонидВедущий специалист по CRM AmSales
Внедряет Битрикс24 и amoCRM, автоматизирует продажи и бизнес-процессы. Золотой партнёр Битрикс24, 400+ проектов.

Коротко: Чтобы улучшить показатель INP, необходимо снизить задержку выполнения JavaScript на основном потоке (Main Thread). Основная стратегия включает устранение Long Tasks (задач длиннее 50 мс), разбиение тяжелых скриптов на мелкие фрагменты, использование Web Workers для фоновых вычислений и удаление неиспользуемого кода через Coverage tool. Хорошим результатом считается значение INP 200 мс и ниже.
Кстати, в AmSales мы делаем внедрение и настройку Битрикс24 и разработку сайтов под ключ под ключ. Если нужна помощь - напишите нам.
Что такое INP и почему 200 мс критичны
Interaction to Next Paint (INP) - это метрика, которая измеряет отзывчивость вашего сайта. Она показывает, насколько быстро пользователь получает визуальный отклик после того, как нажал на кнопку, открыл меню или ввел текст. В отличие от старых метрик, которые смотрели на загрузку страницы, INP оценивает весь жизненный цикл сессии пользователя. Если человек кликает по элементам в течение минуты, INP будет учитывать все эти взаимодействия, а не только самое первое.
Важно понимать, как именно рассчитывается этот показатель. Согласно актуальным данным web.dev на октябрь 2026 года, INP представляет собой 98-й перцентиль всех взаимодействий. Это означает, что если у вас было 100 кликов, и 98 из них прошли быстро, а два были очень медленными, именно эти медленные взаимодействия могут испортить общую картину. Система ищет "узкие места", где пользователь ждет ответа дольше всего.
Почему цифра 200 мс является тем самым водоразделом? Это психологический и технический порог. Когда задержка составляет менее 200 мс, человек воспринимает интерфейс как мгновенный и отзывчивый. Как только время ожидания переваливает за этот предел, возникает ощущение "вязкости" сайта. Пользователь начинает сомневаться, сработал ли клик, и может нажать на кнопку повторно, что порождает еще больше ошибок и лишних запросов к серверу.
Для бизнеса плохой INP - это не просто вопрос эстетики. Это прямая угроза конверсии. В B2B-сегментах, где пользователи работают с тяжелыми интерфейсами (CRM, личные кабинеты, аналитические панели), задержка в полсекунды при открытии выпадающего списка может привести к раздражению и уходу конкурентам. Google официально учитывает INP в Core Web Vitals, а значит, плохая отзывчивость напрямую влияет на позиции сайта в поисковой выдаче.
Три компонента задержки
Чтобы эффективно работать с метрикой, нужно понимать, из чего она складывается. Любое взаимодействие состоит из трех фаз: время ожидания (input delay), время выполнения самого кода (processing time) и время отрисовки кадра (presentation delay). Большинство проблем, которые требуют оптимизации JavaScript для INP, кроются именно во второй фазе - когда браузер занят выполнением тяжелого скрипта и просто не может "услышать" новый клик.
Влияние тяжелых скриптов на задержку ввода
Главный враг отзывчивости - перегруженный Main Thread. В браузере основной поток отвечает за всё: парсинг HTML, расчет стилей, обработку событий и выполнение JavaScript. Если в этот момент запускается тяжелая функция, поток блокируется. Представьте, что вы пытаетесь зайти в магазин, но дверь заклинило, потому что внутри кто-то пытается передвинуть огромный шкаф. Вы стоите перед дверью (вводите запрос), но ничего не происходит, пока шкаф не передвинут.
Тяжелые скрипты создают ситуацию, когда браузер физически не может обработать событие пользователя. Это и есть снижение задержки ввода в негативном ключе. Проблема не всегда в объеме скачанного файла. Даже если ваш JS-файл весит всего 50 КБ, он может содержать цикл, который на несколько секунд вешает страницу. Поэтому оптимизация JavaScript для INP - это не только сжатие кода, но и контроль над тем, когда и как этот код исполняется.
Часто разработчики совершают ошибку, загружая все необходимые функции сразу при старте страницы. В итоге, пока пользователь просто пытается проскроллить ленту, браузер тратит все ресурсы на инициализацию сложных виджетов, которые могут понадобиться только через пять минут. Это создает огромную нагрузку на процессор, особенно на мобильных устройствах с менее мощными чипами, где задержка будет в разы выше, чем на десктопе.
Еще один аспект - это наслоение задач. Если у вас работает анимация, одновременно идет загрузка данных через fetch и инициализируется рекламный баннер, Main Thread оказывается в состоянии постоянной занятости. В такие моменты любое взаимодействие пользователя (например, попытка открыть мобильное меню) попадает в очередь и ждет своей очереди, что резко увеличивает итоговый показатель INP.
Анализ Long Tasks через Chrome DevTools
Нельзя исправить то, что нельзя измерить. Первым шагом к улучшению показателя INP должен стать аудит. Chrome DevTools предоставляет мощный инструментарий для поиска проблемных мест. Вам нужно обратить внимание на раздел Performance. Запишите сессию взаимодействия (например, серию кликов по сайту) и посмотрите на дорожку Main. Ищите блоки, помеченные красным цветом или имеющие длительность более 50 мс. Это и есть Long Tasks.
Long Tasks - это задачи, которые захватывают поток на слишком долгое время. Если задача длится 100 мс, то любое взаимодействие, произошедшее внутри этого интервала, получит задержку как минимум в 100 мс. В инструменте Performance вы можете детально провалиться в каждую такую задачу, увидеть стек вызовов (call stack) и понять, какая именно функция или сторонний скрипт вызвал блокировку.
При анализе важно смотреть не только на длительность, но и на то, что происходит сразу после задачи. Часто одна длинная задача провоцирует цепочку мелких, но тоже заметных задержек. Используйте вкладку "Bottom-Up" и "Call Tree", чтобы определить, какие именно функции потребляют больше всего времени процессора. Это даст вам четкий список целей для рефакторинга.
Также полезно использовать вкладку "Interactions" в последних версиях DevTools. Она позволяет напрямую увидеть, какое конкретное взаимодействие пользователя (клик, нажатие клавиши) привело к высокому значению INP. Это связывает абстрактные цифры метрики с реальным пользовательским опытом, позволяя разработчику сказать: "Ага, вот этот клик по кнопке 'Купить' тормозит из-за функции валидации формы".
На что смотреть в первую очередь:
- Длительность выполнения функции (Execution time).
- Стек вызовов (помогает найти виновника в сторонних библиотеках).
- Взаимосвязь между задачами (не вызывают ли они друг друга по цепочке).
Как разбивать длинные блоки JavaScript кода
Если вы обнаружили Long Task, которая занимает, скажем, 300 мс, ее нельзя просто оставить как есть. Одно из самых эффективных решений - устранение long tasks путем дробления кода. Вместо того чтобы выполнять один огромный блок вычислений, нужно разбить его на серию мелких задач, каждая из которых не превышает 50 мс. Это позволит браузеру "вклиниться" между вашими задачами и обработать ввод пользователя.
Для этого используется механизм планирования задач. В современном JavaScript есть несколько способов сделать это. Самый простой - функция `setTimeout(callback, 0)`. Она не выполняет код мгновенно, а планирует его выполнение в следующем цикле событий. Это дает браузеру микро-паузу, чтобы проверить, не нажал ли пользователь на что-то еще. Однако `setTimeout` - это довольно грубый инструмент.
Более продвинутый и рекомендуемый метод - использование `scheduler.yield()` (если поддерживается браузером) или создание собственной очереди задач. Суть в том, чтобы после выполнения порции работы "отдать управление" браузеру. Это позволяет разгрузить Main Thread и обеспечить плавность интерфейса. Например, если вам нужно отрендерить список из 1000 элементов, не делайте это одним циклом. Сделайте 10 циклов по 100 элементов, прерываясь между ними.
Пример логики разбиения:
- Разделите массив данных на небольшие чанки (порции).
- Обработайте первую порцию.
- Используйте `requestIdleCallback` или `setTimeout`, чтобы запланировать обработку следующей порции.
- Повторяйте, пока данные не закончатся.
Такой подход позволяет избежать ситуации, когда страница "замерзает" на секунду во время обработки тяжелого списка или сложного расчета. Пользователь может продолжать взаимодействовать с сайтом, и его клики будут обработаны в промежутках между вашими микро-задачами.
Использование Web Workers для разгрузки Main Thread
Если у вас есть задачи, которые принципиально не могут быть разбиты на мелкие части (например, сложная математика, обработка больших массивов данных или шифрование), единственный правильный путь - вынос их в Web Workers. Web Workers позволяют запускать JavaScript в фоновом потоке, который полностью изолирован от Main Thread. Это значит, что даже если воркер будет считать уравнение в течение 5 секунд, страница останется идеально отзывчивой.
Это идеальный сценарий для оптимизации JavaScript для INP в сложных веб-приложениях. Например, если ваше приложение должно парсить огромный JSON-файл или обрабатывать изображение на стороне клиента, не делайте это в основном потоке. Отправьте данные в воркер, дождитесь результата через `postMessage` и только потом обновите интерфейс. Таким образом, пользователь никогда не почувствует, что под капотом происходят тяжелые вычисления.
Однако стоит помнить, что использование Web Workers накладывает свои ограничения. У них нет доступа к DOM (Document Object Model). Вы не можете из воркера напрямую изменить цвет кнопки или добавить элемент на страницу. Взаимодействие происходит только через обмен сообщениями. Это требует проектирования архитектуры приложения с учетом того, что логика вычислений и логика отображения разделены.
Также важно учитывать накладные расходы на передачу данных между основным потоком и воркером. Если вы будете пересылать гигантские объекты каждые 10 миллисекунд, вы можете создать новую проблему - задержку на сериализацию и десериализацию данных. Используйте `Transferable objects` (например, ArrayBuffer), чтобы передавать данные без копирования, а не через глубокое клонирование. Это сделает работу воркеров максимально эффективной.
Оптимизация сторонних скриптов и трекинга
Третьи стороны (third-party scripts) - это "черный ящик", который чаще всего является причиной плохого INP. Рекламные сети, чаты поддержки, системы аналитики, пиксели Facebook и Google Tag Manager могут загружать и исполнять огромное количество кода без вашего прямого контроля. Вы можете написать идеальный, оптимизированный код, но один тяжелый виджет чата, который инициализируется при загрузке, обнулит все ваши старания.
Стратегия работы с ними должна быть жесткой. Во-первых, аудит. Если вы не используете какой-то скрипт трекинга уже три месяца - удалите его. Во-вторых, отложенная загрузка (lazy loading). Не загружайте чат поддержки или тяжелый видеоплеер, пока пользователь не доскроллил до них или не нажал на специальную кнопку. Используйте атрибуты `async` и `defer` для скриптов, но помните, что они влияют на порядок загрузки, а не на время выполнения кода после загрузки.
Второй важный метод - использование `requestIdleCallback` для инициализации менее приоритетных сторонних скриптов. Это позволит запустить их только тогда, когда браузер будет находиться в состоянии простоя. Это отличный способ запустить аналитику, не мешая пользователю взаимодействовать с основными функциями сайта. Однако будьте осторожны: если скрипт очень тяжелый, даже в состоянии простоя он может вызвать задержку.
| Тип скрипта | Рекомендация | Приоритет |
| Критическая логика (корзина, авторизация) | Загрузка сразу, оптимизация кода | Высокий |
| Аналитика и трекинг | Отложенная загрузка (Lazy load) | Средний |
| Чаты, виджеты, рекламные баннеры | Загрузка по событию или в idle-режиме | Низкий |
На практике часто помогает создание "прослойки" (wrapper). Вместо того чтобы вставлять сторонний скрипт напрямую, вы вставляете свой легкий скрипт, который создает заглушку. Настоящий скрипт подгружается только тогда, когда это действительно необходимо. Это позволяет полностью контролировать момент, когда сторонний код начнет претендовать на ресурсы Main Thread.
Методы удаления неиспользуемого кода через Coverage
Часто проблема заключается не в том, что код работает медленно, а в том, что браузер тратит время на парсинг и компиляцию огромных объемов JS, которые на данной странице вообще не нужны. Это создает лишнюю нагрузку на процессор при загрузке и может косвенно влиять на INP, так как ресурсы системы заняты обработкой ненужных данных. Для решения этой проблемы в Chrome DevTools есть инструмент Coverage.
Как это работает: вы открываете вкладку Coverage, нажимаете кнопку записи и взаимодействуете со страницей. Инструмент анализирует каждый загруженный файл и показывает процент кода, который не был выполнен. Вы можете увидеть, что, например, в библиотеке для работы с формами используется только 10% функций, а остальные 90% просто занимают место и нагружают систему при парсинге.
Увидев такие цифры, у вас есть три пути. Первый - самый правильный: использовать Tree Shaking. Современные сборщики (Webpack, Rollup, Vite) умеют удалять неиспользуемый код, если вы правильно импортируете модули. Вместо `import _ from 'lodash'` используйте `import debounce from 'lodash/debounce'`. Это позволит уменьшить объем загружаемого кода в разы.
Второй путь - динамический импорт (`import()`). Если вы видите через Coverage, что определенный кусок кода нужен только в одном сценарии (например, при открытии модального окна), не загружайте его в основном бандле. Загружайте его только в момент вызова функции. Это не только уменьшит размер основного файла, но и разгрузит Main Thread в момент начальной загрузки страницы, что положительно скажется на всех метриках взаимодействия.
Третий путь - если вы используете тяжелые CSS-фреймворки, аналогичный подход применим и к ним. Удаление неиспользуемых стилей через Coverage помогает не только ускорить отрисовку (LCP/CLS), но и снижает общую сложность вычислений, которую браузер выполняет при каждом изменении DOM, что косвенно разгружает поток для обработки ввода.
Стратегия минимизации задержек при взаимодействии
Чтобы окончательно закрепить результат, нужно перейти от точечного исправления ошибок к системному подходу. Оптимизация INP - это не разовая акция, а процесс постоянного мониторинга. Ваша стратегия должна строиться на трех столпах: предотвращение блокировок, приоритизация ввода и мониторинг реальных пользователей (RUM).
Во-первых, всегда приоритизируйте ввод. Если на странице происходит несколько процессов одновременно, пользовательский ввод должен иметь наивысший приоритет. Используйте современные API для управления приоритетами задач. Если вы планируете тяжелую задачу, которая не критична для текущего момента, помечайте ее как низкоприоритетную. Это гарантирует, что когда пользователь нажмет на кнопку, браузер мгновенно переключится на его задачу.
Во-вторых, внедрите проверку на "тяжелые" взаимодействия в ваш CI/CD процесс. Можно настроить автоматизированные тесты (например, через Lighthouse CI), которые будут проверять показатели отзывчивости на каждом пулл-реквесте. Если новый функционал увеличивает время выполнения задач на Main Thread выше допустимого порога, сборка должна отклоняться. Это предотвратит деградацию INP в будущем.
В-третьих, не полагайтесь только на лабораторные данные (Lighthouse). Lab-данные показывают, как сайт работает в идеальных условиях. Но INP - это метрика, основанная на реальных пользователях. Используйте Field Data (данные из Google Search Console или систем мониторинга типа Sentry/New Relic). Только они покажут, как ваш сайт ведет себя на бюджетных Android-смартфонах в условиях плохого 3G-соединения, где задержки могут быть в 10 раз выше, чем в вашем DevTools.
Чек-лист для оптимизации INP:
- Проведен аудит Long Tasks через Performance tab.
- Тяжелые вычисления вынесены в Web Workers.
- Длинные циклы и функции разбиты на мелкие части через scheduler.yield или setTimeout.
- Сторонние скрипты загружаются отложенно или по событию.
- Неиспользуемый код удален с помощью Coverage tool и Tree Shaking.
- Настроено отслеживание Field Data для мониторинга реального опыта пользователей.
Помните, что идеальный сайт - это не тот, где нет тяжелых задач, а тот, где эти задачи не мешают человеку управлять интерфейсом. Снижение задержки ввода - это в первую очередь про уважение к времени и комфорту вашего пользователя.
/ Поможем с этим