Frontend3 min czytania

INP w praktyce: jak znaleźć i naprawić wolne kliknięcia

Interaction to Next Paint mierzy, ile użytkownik czeka na reakcję strony. Pokazuję, jak zmierzyć INP w terenie i jak rozbić długie zadania.

inp

Zdjęcie ilustracyjne: Unsplash

Od marca 2024 roku Interaction to Next Paint jest jednym z trzech Core Web Vitals i zastąpił FID. Różnica jest zasadnicza: FID mierzył tylko opóźnienie pierwszej interakcji, a INP patrzy na wszystkie kliknięcia, dotknięcia i naciśnięcia klawiszy w czasie całej wizyty — i raportuje jedną z najgorszych.

Co dokładnie mierzy INP

Każda interakcja składa się z trzech części. Wolna może być każda z nich, więc najpierw trzeba wiedzieć, która.

  • Input delay — czas, zanim przeglądarka w ogóle zacznie obsługiwać zdarzenie, bo główny wątek jest zajęty czymś innym.
  • Processing time — czas wykonania Twoich handlerów.
  • Presentation delay — przeliczenie stylów, layout i malowanie następnej klatki.
WynikINP (75. percentyl)
Dobry≤ 200 ms
Do poprawy200–500 ms
Słaby> 500 ms

Zmierz w terenie, nie tylko w laboratorium

Lighthouse nie klika za użytkownika, więc nie pokaże prawdziwego INP. Potrzebne są dane z prawdziwych sesji. Najprościej: biblioteka web-vitals z buildem attribution, która od razu mówi, który element i która faza zawiodły.

import { onINP } from 'web-vitals/attribution';

onINP(({ value, attribution }) => {
  const { interactionTarget, inputDelay, processingDuration, presentationDelay } = attribution;
  navigator.sendBeacon('/vitals', JSON.stringify({
    value, interactionTarget, inputDelay, processingDuration, presentationDelay,
  }));
});

Po tygodniu zbierania zwykle widać, że problem robi kilka konkretnych elementów: filtr w sklepie, przycisk „dodaj do koszyka”, menu na telefonie.

Rozbij długie zadania

Najczęstsza przyczyna złego INP to handler, który robi wszystko naraz: aktualizuje stan, przelicza listę, wysyła analitykę. Przeglądarka nie może narysować klatki, dopóki to się nie skończy. Rozwiązanie: zrobić to, co widać, od razu, a resztę oddać po kawałku.

function yieldToMain() {
  if ('scheduler' in window && 'yield' in scheduler) return scheduler.yield();
  return new Promise((resolve) => setTimeout(resolve, 0));
}

button.addEventListener('click', async () => {
  showSpinner();            // użytkownik od razu widzi reakcję
  await yieldToMain();
  applyFilters();
  await yieldToMain();
  sendAnalytics();
});

Wskazówka Panel Performance w Chrome DevTools pokazuje teraz interakcje na osobnej ścieżce i oznacza te dłuższe niż 200 ms. Nagraj kliknięcie i szukaj czerwonych trójkątów.

Szybkie wygrane

  • Odłóż skrypty firm trzecich (czat, mapy ciepła) do czasu po interakcji lub bezczynności.
  • Zmniejsz DOM — tysiące węzłów to droższy layout przy każdej zmianie.
  • Użyj content-visibility: auto dla sekcji poniżej ekranu.
  • Nie czytaj wymiarów (offsetHeight) zaraz po zmianie stylów w pętli — to wymusza synchroniczny layout.

INP rzadko naprawia się jedną zmianą. Ale zwykle wystarczą trzy, cztery celne poprawki w najczęściej klikanych miejscach, żeby zejść poniżej 200 ms.

STOS

Blog o frontendzie, DevOps i narzędziach

Zbudowany na WordPressie: własny motyw blokowy, Polylang, Yoast SEO. Zobacz panel WordPressa w Playground ↗

STOS to fikcyjny blog — projekt koncepcyjny do portfolio. Autorka i treści są przykładowe.