INP заменил FID два года назад — что показала практика

Замерил INP на 30 средних сайтов из своих проектов. У 22 — жёлтая или красная зона. Разбираю почему и что реально помогает.

редакция seodb#core-web-vitals#аудит

Прогнал INP через CrUX и PageSpeed Insights на 30 средних сайтах из своей практики за апрель. Итог: 8 в зелёной зоне, 14 в жёлтой, 8 в красной. У 22 из 30 сайтов метрика формально не в норме. И это не мусор — это малый SaaS, локальный бизнес, медиа. Нормальные проекты, которые год назад были в зелёной зоне по FID.

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

Что произошло два года назад

Google заменил FID на INP как Core Web Vital 12 марта 2024. Прошло почти два года — данных накопилось много, и они складываются в неутешительную картину. По обзорным данным HTTP Archive на конец 2024-го, 60% сайтов в CrUX были в жёлтой или красной зоне по INP. За 2025-й ситуация улучшилась — примерно 55% всё ещё вне зелёной зоны. Улучшение есть, но медленное.

Пороги для тех, кто забыл:

  • Good: ≤ 200 мс
  • Needs Improvement: 200–500 мс
  • Poor: > 500 мс

Это field data — реальные пользователи, реальные устройства. Не то, что показывает Lighthouse в идеальных лабораторных условиях. И тут кроется главная ловушка: сайт с Lighthouse-скором 95 в PageSpeed Insights может при этом иметь INP 450 мс в поле. Это регулярно вижу у SPA-приложений и тяжёлых WordPress-сборок с 15 плагинами.

Почему INP жёстче, чем казалось

FID мерил время до первой реакции интерфейса. Если у вас на главной кнопка «Открыть меню» отвечает за 80 мс — FID зелёный, независимо от того, что происходит дальше на других страницах.

INP смотрит на все взаимодействия за сессию и берёт из них 98-й перцентиль. Не худший клик, не первый — а тот, который хуже 98% остальных. И этот показатель обычно даёт куда более честную картину. У кнопки «Открыть меню» всё нормально, но на карточке товара клик по «Добавить в корзину» отвечает через 380 мс, потому что там висит event handler на 8 килобайт JS-кода — и вот вам жёлтая зона.

Из моей практики главные виновники — три вещи, и они повторяются с проекта на проект.

Первое — тяжёлые event handlers. Классика: onClick, который синхронно вызывает 15 функций, каждая из которых что-то читает из DOM. Пока весь этот стек отработает, браузер не может отрисовать реакцию на клик — и INP улетает вверх. Чинится вынесением всего, что можно, в setTimeout или requestIdleCallback. Не всегда красиво, но работает.

Второе — большие сторонние скрипты. Аналитика, чат-виджет, рекламные сети — все они блокируют main thread. Вопрос не в том, чтобы удалить их, а в том, чтобы загружать асинхронно и по возможности откладывать до первого взаимодействия. У одного клиентского проекта после переноса чат-виджета в загрузку по клику INP упал с 470 до 220 мс — на всём сайте, за одну правку.

Третье — тяжёлый рендер списков без виртуализации. Это уже про SPA и React/Vue-приложения. Если у вас в фиде 200 карточек, каждая рендерит компонент на 15 хуков, при скролле любой клик отвечает медленно. Виртуализация решает — но её надо ставить с самого начала, а не «когда сайт уже готов».

Как замерять на своём сайте — правильно

Тут важно не спутать field data и lab data.

Lab data — это то, что показывает Lighthouse в браузере или в CI. Синтетический замер на идеальных условиях. Полезно для проверки, что вы не сделали хуже последним релизом. Но абсолютные значения из Lighthouse не совпадают с тем, что видит Google в CrUX.

Field data — то, что Google собирает от реальных пользователей в Chrome. Именно эти данные учитываются в ранжировании. Смотреть их можно в трёх местах: PageSpeed Insights, Search Console → отчёт «Core Web Vitals», CrUX Dashboard в Data Studio для больших сайтов.

Правило простое: чинить надо то, что видно в field data. Если Lighthouse говорит «INP 180», а CrUX показывает 380 — верить надо CrUX. Пользователи Google видят именно его.

Что реально помогает — короткий список

По итогам работы с 12-ю проектами, где INP был проблемой:

Разгрузить main thread от синхронного JS. Всё, что можно, — в async/defer. Всё, что нельзя, — в setTimeout или requestIdleCallback. Это даёт основной выигрыш.

Убить лишние event handlers. Особенно те, что вешаются глобально на document или window. Проверить через Chrome DevTools → Performance → Long Tasks — что происходит в момент клика.

Отложить сторонние скрипты. Чат, аналитика, реклама — всё, что можно, грузить не сразу, а по взаимодействию или после DOMContentLoaded + 3 секунды.

Виртуализовать длинные списки. Для React — react-window или react-virtual. Для Vue — vue-virtual-scroller. Для обычных сайтов — не рендерить больше 50 элементов в начальной загрузке.

Проверять не Lighthouse, а CrUX. Хотя бы раз в месяц заглядывать в Search Console → Core Web Vitals. Если жёлтые страницы в списке не меняются — значит проблема не решена.

Что сделать за час прямо сейчас. Откройте PageSpeed Insights, вставьте URL своей главной, посмотрите блок «Discover what your real users are experiencing». Если INP там больше 200 мс — переключитесь на конкретную страницу (обычно карточка товара или форма) и повторите. Найдёте страницу с INP >400 — начинайте с неё, не с главной. Именно там, где пользователь реально что-то делает, метрика режется сильнее всего.