Главная / База знаний / Скорость и Core Web Vitals / INP плохой — клики на сайте отвечают медленно
База знаний

INP плохой — клики на сайте отвечают медленно

Interaction to Next Paint > 200ms. Тяжёлый JS, большой DOM, слишком много обработчиков.

Скорость и Core Web Vitals · 3 мин чтения

Симптом

Причина

  1. Тяжёлый JavaScript
    - Большой объём кода, который загружается сразу (не‑ленивый импорт).
    - Синхронные операции (heavy loops, DOM‑манипуляции, парсинг больших JSON‑файлов).
    - Неоптимизированные библиотеки, которые блокируют основной поток.

  2. Большой DOM
    - Слишком много элементов, особенно вложенных, что увеличивает время рендеринга и пересчёта стилей.
    - Частые изменения структуры DOM (добавление/удаление узлов) в ответ на клик.

  3. Много обработчиков событий
    - Один и тот же элемент имеет десятки addEventListener.
    - Обработчики регистрируются в цикле, создавая «обёртки» и лишние вызовы.

  4. Синхронные запросы
    - fetch/XMLHttpRequest в обработчике клика, которые блокируют UI‑поток до завершения.

  5. Плохая оптимизация рендеринга
    - requestAnimationFrame не используется, а вместо этого setTimeout/setInterval.
    - Необъёмные стили, которые пересчитываются каждый раз при клике.

Как проверить

  1. DevTools → Performance → Record
    - Запишите сессии с кликом.
    - Посмотрите длительность задач (Long Tasks) и их количество.
    - Оцените время до первого «paint» после клика.

  2. Lighthouse
    - Запустите Lighthouse в режиме «Performance» и посмотрите раздел «Interaction to Next Paint».

  3. Chrome User Experience Report
    - Откройте https://web.dev/innp/ и посмотрите реальные показатели INP для вашего сайта.

  4. Проверка JavaScript
    - В DevTools → Sources → Coverage: включите покрытие и посмотрите, какие файлы загружаются и сколько кода реально исполняется.
    - В профайлере → JavaScript → Event Listeners просмотрите количество обработчиков на элементе.

  5. Проверка DOM
    - В DevTools → Elements → :nth-child и :nth-of-type посмотрите глубину вложенности.
    - Считайте количество узлов: document.querySelectorAll('*').length.

  6. Проверка запросов
    - В Network вкладке посмотрите, какие запросы отправляются в обработчике клика и сколько времени они занимают.

Решение

1. Разделить JavaScript на чанки

// Вместо
import heavyLib from './heavyLib.js';
// используйте
import(/* webpackChunkName: "heavyLib" */ './heavyLib.js')
  .then(module => {
    // обработка после загрузки
  });

Lazy‑load скрипты, которые нужны только после клика.

2. Уменьшить размер DOM

const frag = document.createDocumentFragment();
for (const item of items) {
  const el = document.createElement('div');
  el.textContent = item;
  frag.appendChild(el);
}
container.appendChild(frag);

3. Оптимизировать обработчики событий

document.body.addEventListener('click', function (e) {
  if (e.target.matches('.btn')) {
    handleClick(e.target);
  }
});

4. Перенести тяжёлые расчёты в Web Worker

// worker.js
onmessage = function(e) {
  const result = heavyCalculation(e.data);
  postMessage(result);
};
// main.js
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.onmessage = function(e) {
  updateUI(e.data);
};

5. Использовать requestAnimationFrame для анимаций

function animate() {
  // обновление позиции
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

6. Минимизировать синхронные запросы

async function onClick() {
  const data = await fetchData(); // не блокирует UI
  render(data);
}

7. Сократить пересчёт стилей

.button {
  will-change: transform;
}

8. Проверить после изменений

Связанные

SEO КП · нужна помощь?

Не хотите разбираться сами?

Запустите технический аудит сайта за 5 минут — получите PDF-отчёт с разбором всех 64 параметров и конкретными точками роста. Или закажите комплексное SEO-продвижение сайта — починим всё это и возьмём на себя дальнейшую оптимизацию.

Запустить аудит за 199 ₽ Узнать про продвижение →