Dowiedz się, jak zoptymalizować czas od interakcji do kolejnego wyrenderowania w witrynie.
Data publikacji: 19 maja 2023 r., ostatnia aktualizacja: 2 września 2025 r.
Interakcja do kolejnego wyrenderowania (INP) to stabilny podstawowy wskaźnik internetowy, który ocenia ogólną responsywność strony na interakcje użytkowników na podstawie obserwacji czasu oczekiwania w odniesieniu do wszystkich kwalifikujących się interakcji w całym okresie odwiedzania strony przez użytkownika. Ostateczna wartość INP to najdłuższa zaobserwowana interakcja (czasami z pominięciem wartości odstających).
Aby zapewniać użytkownikom dobre wrażenia, wartość interakcji do kolejnego wyrenderowania powinna wynosić 200 milisekund lub mniej. Aby osiągnąć ten cel w przypadku większości użytkowników, dobrym progiem do zmierzenia jest 75 percentyl wczytywania stron, podzielony na urządzenia mobilne i komputery.
W zależności od witryny może być niewiele interakcji lub może ich nie być wcale – na przykład na stronach zawierających głównie tekst i obrazy z niewielką liczbą elementów interaktywnych lub bez nich. W przypadku witryn takich jak edytory tekstu lub gry może być ich setki, a nawet tysiące. W obu przypadkach, gdy INP jest wysoki, wygoda użytkowników jest zagrożona.
Poprawa INP wymaga czasu i wysiłku, ale nagrodą są lepsze wrażenia użytkowników. W tym przewodniku omówimy sposób poprawy INP.
Ustalanie przyczyny niskiego INP
Zanim zaczniesz rozwiązywać problemy z powolnymi interakcjami, musisz mieć dane, które pozwolą Ci stwierdzić, czy wskaźnik INP Twojej witryny jest słaby lub wymaga poprawy. Gdy masz już te informacje, możesz przejść do laboratorium, aby zacząć diagnozować powolne interakcje i pracować nad rozwiązaniem.
Znajdowanie powolnych interakcji w terenie
Najlepiej zacząć optymalizację INP od danych zgromadzonych przez użytkowników. W najlepszym przypadku dane zgromadzone przez dostawcę usługi monitorowania rzeczywistych użytkowników (RUM) dostarczą nie tylko wartości INP strony, ale też danych kontekstowych, które wskazują, jaka konkretna interakcja odpowiada za wartość INP, czy interakcja miała miejsce podczas wczytywania strony czy po nim, jaki był typ interakcji (kliknięcie, naciśnięcie klawisza czy dotknięcie) oraz inne cenne informacje.
Jeśli nie korzystasz z usług dostawcy RUM, aby uzyskać dane z pól, w przewodniku po danych z pól INP znajdziesz poradę, aby użyć PageSpeed Insights do wyświetlenia danych z Raportu na temat użytkowania Chrome (CrUX), co pomoże Ci uzupełnić luki. CrUX to zbiór danych Google w ramach programu Core Web Vitals, który zawiera ogólne podsumowanie danych dotyczących milionów witryn, w tym INP. CrUX często nie dostarcza jednak danych kontekstowych, które można uzyskać od dostawcy RUM, aby pomóc w analizie problemów. Dlatego zalecamy, aby w miarę możliwości witryny korzystały z usług dostawcy RUM lub wdrażały własne rozwiązanie RUM, które uzupełni dane dostępne w CrUX.
Diagnozowanie powolnych interakcji w laboratorium
Najlepiej zacząć testowanie w laboratorium, gdy masz dane zgromadzone przez użytkowników, które sugerują, że interakcje są powolne. Jeśli nie masz danych zgromadzonych, możesz zastosować kilka strategii identyfikowania powolnych interakcji w laboratorium. Takie strategie obejmują śledzenie typowych wzorców przeglądania i testowanie interakcji po drodze, a także interakcję ze stroną podczas wczytywania, gdy wątek główny jest często najbardziej obciążony, aby zidentyfikować powolne interakcje podczas tej kluczowej części wrażeń użytkownika.
Optymalizacja interakcji
Gdy zidentyfikujesz powolną interakcję i będziesz w stanie odtworzyć ją ręcznie w laboratorium, następnym krokiem będzie jej optymalizacja.
Interakcje można podzielić na 3 podkategorie:
- Opóźnienie przy działaniu, które zaczyna się, gdy użytkownik inicjuje interakcję ze stroną, a kończy, gdy zaczynają się wykonywać wywołania zwrotne zdarzenia związane z interakcją.
- czas przetwarzania, czyli czas potrzebny na wykonanie wywołań zwrotnych zdarzeń.
- opóźnienie prezentacji, czyli czas potrzebny przeglądarce na wyświetlenie następnej klatki, która zawiera wizualny wynik interakcji.
Suma tych 3 części składowych to całkowity czas oczekiwania na interakcję. Każda część interakcji przyczynia się do całkowitego opóźnienia interakcji, dlatego ważne jest, aby wiedzieć, jak zoptymalizować każdą część interakcji, aby działała jak najkrócej.
Identyfikowanie i zmniejszanie opóźnienia wejściowego
Gdy użytkownik wchodzi w interakcję ze stroną, pierwszą częścią tej interakcji jest opóźnienie przy działaniu. W zależności od innych działań na stronie opóźnienia przy wprowadzaniu danych mogą być znaczne. Może to być spowodowane aktywnością w głównym wątku (np. wczytywaniem, analizowaniem i kompilowaniem skryptów), obsługą pobierania, funkcjami licznika czasu, a nawet innymi interakcjami, które występują w krótkich odstępach czasu i nakładają się na siebie.
Niezależnie od źródła opóźnienia wejściowego interakcji należy je ograniczyć do minimum, aby interakcje mogły jak najszybciej zacząć uruchamiać wywołania zwrotne zdarzeń.
Związek między oceną skryptu a długimi zadaniami podczas uruchamiania
Kluczowym aspektem interaktywności w cyklu życia strony jest uruchamianie. Podczas wczytywania strony jest ona najpierw renderowana, ale należy pamiętać, że to, że strona została wyrenderowana, nie oznacza, że została w pełni wczytana. W zależności od tego, ile zasobów wymaga strona, aby stać się w pełni funkcjonalna, użytkownicy mogą próbować wejść z nią w interakcję, gdy jeszcze się wczytuje.
Jedną z rzeczy, które mogą wydłużyć opóźnienie wejściowe interakcji podczas wczytywania strony, jest ocena skryptu. Po pobraniu pliku JavaScript z sieci przeglądarka musi jeszcze wykonać pewne czynności, zanim będzie mogła go uruchomić. Obejmują one analizę skryptu w celu sprawdzenia, czy jego składnia jest prawidłowa, skompilowanie go do kodu bajtowego, a następnie wykonanie.
W zależności od rozmiaru skryptu może to powodować długie zadania w głównym wątku, co opóźni reakcję przeglądarki na inne interakcje użytkownika. Aby strona reagowała na działania użytkownika podczas wczytywania, musisz wiedzieć, co możesz zrobić, aby zmniejszyć prawdopodobieństwo wystąpienia długich zadań podczas wczytywania strony, dzięki czemu będzie ona działać szybko.
Optymalizacja wywołań zwrotnych zdarzeń
Opóźnienie wejściowe to tylko pierwsza część tego, co mierzy INP. Musisz też zadbać o to, aby wywołania zwrotne zdarzeń, które są uruchamiane w odpowiedzi na interakcję użytkownika, mogły zostać wykonane jak najszybciej.
Często przekazuj sterowanie do wątku głównego
Najlepszą ogólną radą dotyczącą optymalizacji wywołań zwrotnych zdarzeń jest wykonywanie w nich jak najmniejszej liczby działań. Logika interakcji może być jednak złożona i możesz tylko nieznacznie ograniczyć ich pracę.
Jeśli tak jest w przypadku Twojej witryny, możesz spróbować podzielić pracę w wywołaniach zwrotnych zdarzeń na osobne zadania. Dzięki temu zbiorcze zadanie nie stanie się długim zadaniem, które blokuje wątek główny, co pozwala na szybsze uruchamianie innych interakcji, które w przeciwnym razie czekałyby na wątek główny.
setTimeout to jeden ze sposobów na podział zadań, ponieważ przekazywane do niego wywołanie zwrotne jest uruchamiane w nowym zadaniu. Możesz użyć funkcji setTimeout samodzielnie lub wyodrębnić jej użycie do osobnej funkcji, aby uzyskać bardziej ergonomiczne przekazywanie.
Przekazywanie bez rozróżnienia jest lepsze niż brak przekazywania, ale istnieje bardziej szczegółowy sposób przekazywania do wątku głównego, który polega na przekazywaniu tylko bezpośrednio po wywołaniu zwrotnym zdarzenia, które aktualizuje interfejs użytkownika, dzięki czemu logika renderowania może działać szybciej.
Zrezygnuj z wykonywania zadań, aby umożliwić szybsze renderowanie
Bardziej zaawansowana technika przekazywania polega na takim ustrukturyzowaniu kodu w wywołaniach zwrotnych zdarzeń, aby ograniczyć to, co jest uruchamiane, tylko do logiki wymaganej do zastosowania aktualizacji wizualnych w następnej klatce. Wszystko inne można odłożyć na później. Dzięki temu wywołania zwrotne są lekkie i szybkie, a czas renderowania interakcji jest krótszy, ponieważ aktualizacje wizualne nie są blokowane przez kod wywołania zwrotnego zdarzenia.
Wyobraź sobie na przykład edytor tekstu sformatowanego, który formatuje tekst podczas pisania, ale też aktualizuje inne aspekty interfejsu w odpowiedzi na to, co zostało napisane (np. liczbę słów, wyróżnianie błędów pisowni i inne ważne informacje wizualne). Dodatkowo aplikacja może potrzebować zapisać to, co zostało napisane, aby po opuszczeniu i powrocie nie stracić żadnych danych.
W tym przykładzie w odpowiedzi na znaki wpisywane przez użytkownika muszą nastąpić 4 zdarzenia. Jednak tylko pierwszy element musi zostać wykonany przed wyświetleniem następnej klatki.
- Zaktualizuj pole tekstowe, wpisując tekst wpisany przez użytkownika, i zastosuj wymagane formatowanie.
- Zaktualizuj część interfejsu, która wyświetla bieżącą liczbę słów.
- Uruchom logikę, aby sprawdzić błędy pisowni.
- Zapisz najnowsze zmiany (lokalnie lub w zdalnej bazie danych).
Kod, który to umożliwia, może wyglądać tak:
textBox.addEventListener('input', (inputEvent) => {
// Update the UI immediately, so the changes the user made
// are visible as soon as the next frame is presented.
updateTextBox(inputEvent);
// Use `setTimeout` to defer all other work until at least the next
// frame by queuing a task in a `requestAnimationFrame()` callback.
requestAnimationFrame(() => {
setTimeout(() => {
const text = textBox.textContent;
updateWordCount(text);
checkSpelling(text);
saveChanges(text);
}, 0);
});
});
Poniższa wizualizacja pokazuje, jak odroczenie wszelkich niekrytycznych aktualizacji do czasu po następnej klatce może skrócić czas przetwarzania, a tym samym ogólny czas oczekiwania na interakcję.
Chociaż użycie setTimeout() w wywołaniu requestAnimationFrame() w poprzednim przykładzie kodu jest nieco ezoteryczne, jest to skuteczna metoda, która działa we wszystkich przeglądarkach i zapobiega blokowaniu następnej klatki przez niekrytyczny kod.
Unikaj niszczenia układu
Przeładowanie układu (czasami nazywane wymuszonym układem synchronicznym) to problem z wydajnością renderowania, który występuje, gdy układ jest renderowany synchronicznie. Dzieje się tak, gdy aktualizujesz style w kodzie JavaScript, a następnie odczytujesz je w tym samym zadaniu. W kodzie JavaScript jest wiele właściwości, które mogą powodować przeciążenie układu.
Przeciążenie układu jest wąskim gardłem wydajności, ponieważ aktualizowanie stylów, a następnie natychmiastowe żądanie wartości tych stylów w kodzie JavaScript zmusza przeglądarkę do wykonywania synchronicznych zadań związanych z układem, które w przeciwnym razie mogłyby zostać wykonane asynchronicznie po zakończeniu wywołań zwrotnych zdarzeń.
Zminimalizuj opóźnienie prezentacji
Opóźnienie prezentacji interakcji obejmuje czas od zakończenia wykonywania wywołań zwrotnych zdarzenia interakcji do momentu, w którym przeglądarka może wyrenderować następną klatkę, która pokazuje wynikające z tego zmiany wizualne.
Zminimalizuj rozmiar DOM
Gdy DOM strony jest mały, renderowanie zwykle kończy się szybko. Jednak gdy drzewa DOM stają się bardzo duże, zadania renderowania zwykle skalują się wraz ze wzrostem rozmiaru DOM. Zależność między renderowaniem a rozmiarem DOM nie jest liniowa, ale duże elementy DOM wymagają więcej pracy przy renderowaniu niż małe. Duży DOM jest problematyczny w 2 przypadkach:
- podczas początkowego renderowania strony, gdy duży DOM wymaga dużo pracy, aby wyrenderować początkowy stan strony;
- W odpowiedzi na interakcję użytkownika, gdy duży DOM może spowodować, że aktualizacje renderowania będą bardzo kosztowne, a tym samym wydłuży się czas potrzebny przeglądarce na wyświetlenie następnej klatki.
Pamiętaj, że w niektórych przypadkach nie da się znacznie zmniejszyć dużych drzew DOM. Możesz zmniejszyć rozmiar DOM, na przykład przez spłaszczenie DOM lub dodawanie do DOM podczas interakcji użytkownika, aby zachować mały rozmiar początkowy DOM, ale te techniki mogą nie wystarczyć.
Używaj content-visibility do leniwego renderowania elementów poza ekranem
Jednym ze sposobów na ograniczenie ilości pracy związanej z renderowaniem podczas wczytywania strony i w odpowiedzi na interakcje użytkownika jest użycie właściwości CSS content-visibility, która skutecznie opóźnia renderowanie elementów, gdy zbliżają się do widocznego obszaru. Chociaż skuteczne korzystanie z interfejsu content-visibility może wymagać pewnej wprawy, warto sprawdzić, czy jego użycie pozwala skrócić czas renderowania, co może poprawić INP strony.
Pamiętaj o kosztach związanych z wydajnością podczas renderowania kodu HTML za pomocą JavaScriptu
Tam, gdzie jest HTML, występuje też jego analizowanie. Gdy przeglądarka zakończy analizowanie kodu HTML i przekształcanie go w DOM, musi zastosować do niego style, wykonać obliczenia układu, a następnie wyrenderować ten układ. Jest to nieunikniony koszt, ale sposób renderowania kodu HTML ma znaczenie.
Gdy serwer wysyła kod HTML, dociera on do przeglądarki jako strumień. Strumieniowanie oznacza, że odpowiedź HTML z serwera dociera we fragmentach. Przeglądarka optymalizuje sposób obsługi strumienia, analizując przyrostowo fragmenty strumienia w miarę ich docierania i renderując je po kolei. Jest to optymalizacja wydajności, ponieważ przeglądarka domyślnie i automatycznie przekazuje kontrolę podczas wczytywania strony, co nie wymaga żadnych działań z Twojej strony.
Podczas pierwszej wizyty w dowolnej witrynie zawsze pobierana jest pewna ilość kodu HTML. Typowe podejście polega na tym, że na początku pobierana jest minimalna ilość kodu HTML, a następnie do wypełnienia obszaru treści używany jest JavaScript. Kolejne aktualizacje tego obszaru treści również następują w wyniku interakcji użytkownika. Jest to tzw. model aplikacji jednostronicowej. Wadą tego wzorca jest to, że renderowanie kodu HTML za pomocą JavaScriptu po stronie klienta nie tylko wiąże się z kosztem przetwarzania JavaScriptu w celu utworzenia tego kodu HTML, ale też przeglądarka nie zwróci wyniku, dopóki nie zakończy analizowania i renderowania tego kodu HTML.
Warto jednak pamiętać, że nawet witryny, które nie są aplikacjami jednostronicowymi, prawdopodobnie będą wymagały renderowania kodu HTML za pomocą JavaScriptu w wyniku interakcji. Zwykle nie jest to problem, o ile nie renderujesz dużych ilości kodu HTML po stronie klienta, co może opóźnić wyświetlanie następnej klatki. Ważne jest jednak, aby zrozumieć, jak takie podejście do renderowania kodu HTML w przeglądarce wpływa na wydajność i jak może wpłynąć na szybkość reagowania witryny na działania użytkownika, jeśli renderujesz dużo kodu HTML za pomocą JavaScriptu.
Podsumowanie
Poprawianie INP witryny to proces iteracyjny. Gdy naprawisz powolną interakcję w terenie, istnieje duże prawdopodobieństwo, że – zwłaszcza jeśli Twoja witryna zapewnia wiele interaktywności – zaczniesz znajdować inne powolne interakcje i będziesz musiał je również zoptymalizować.
Kluczem do poprawy INP jest wytrwałość. Z czasem możesz poprawić responsywność strony do poziomu, który będzie zadowalać użytkowników. Istnieje też duże prawdopodobieństwo, że podczas opracowywania nowych funkcji dla użytkowników konieczne będzie przeprowadzenie tego samego procesu optymalizacji interakcji, które są dla nich specyficzne. Będzie to wymagało czasu i wysiłku, ale warto je poświęcić.