Dowiedz się, jak zoptymalizować czas od interakcji do kolejnego wyrenderowania w swojej 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, które występują 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, witryny powinny mieć wartość interakcji do kolejnego wyrenderowania nie większą niż 200 milisekund. 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 nie być ich wcale – np. strony zawierające głównie tekst i obrazy z niewielką liczbą elementów interaktywnych lub bez nich. W przypadku witryn takich jak edytory tekstu czy gry może ich być setki, a nawet tysiące. W obu przypadkach, gdy INP jest wysoki, wrażenia użytkownika są zagrożone.
Poprawa INP wymaga czasu i wysiłku, ale nagrodą są lepsze wrażenia użytkowników. W tym przewodniku omówimy sposoby poprawy INP.
Ustalanie przyczyny niskiego wyniku INP
Zanim zaczniesz rozwiązywać problemy z powolnymi interakcjami, musisz mieć dane, które pozwolą Ci określić, czy wskaźnik INP Twojej witryny jest niski lub wymaga poprawy. Gdy uzyskasz te informacje, możesz przejść do modułu, aby rozpocząć diagnozowanie powolnych interakcji i znaleźć rozwiązanie.
Znajdowanie powolnych interakcji w terenie
Najlepiej zacząć optymalizację INP od danych z terenu. W najlepszym przypadku dane z pomiarów w terenie od dostawcy monitorowania użytkowników w czasie rzeczywistym (RUM) dostarczą Ci nie tylko wartości INP strony, ale też dane kontekstowe, które wskazują, która konkretna interakcja odpowiada za wartość INP, czy wystąpiła ona podczas wczytywania strony, czy po nim, jaki był jej rodzaj (kliknięcie, naciśnięcie klawisza lub dotknięcie) oraz inne cenne informacje.
Jeśli nie korzystasz z usługi RUM, aby uzyskiwać dane z pól, przewodnik po danych z pól dotyczących INP zaleca korzystanie z PageSpeed Insights do wyświetlania danych z Raportu na temat użytkowania Chrome (CrUX), aby uzupełnić braki. CrUX to zbiór danych Google dotyczący programu podstawowych wskaźników internetowych. Zawiera on ogólne podsumowanie wskaźników dla milionów witryn, w tym INP. CrUX często nie dostarcza jednak danych kontekstowych, które pomagają w analizowaniu problemów i które można uzyskać od dostawcy RUM. Dlatego nadal zalecamy, aby witryny w miarę możliwości korzystały z usługi RUM lub wdrażały własne rozwiązanie RUM, które uzupełni dane dostępne w CrUX.
Diagnozowanie powolnych interakcji w laboratorium
Testowanie w laboratorium najlepiej rozpocząć, gdy dane z terenu wskazują na powolne interakcje. W przypadku braku danych z terenu można zastosować kilka strategii identyfikowania powolnych interakcji w laboratorium. Takie strategie obejmują śledzenie typowych ścieżek użytkowników i testowanie interakcji na tych ścieżkach, a także interakcje ze stroną podczas ładowania – gdy główny wątek jest często najbardziej obciążony – w celu zidentyfikowania powolnych interakcji w tej kluczowej części doświadczenia użytkownika.
Optymalizowanie interakcji
Gdy zidentyfikujesz powolną interakcję i będziesz w stanie ręcznie odtworzyć ją w warunkach laboratoryjnych, następnym krokiem będzie jej optymalizacja.
Interakcje można podzielić na 3 części:
- Opóźnienie przy wprowadzaniu danych, które rozpoczyna się, gdy użytkownik rozpoczyna interakcję ze stroną, a kończy, gdy zaczynają się wykonywać wywołania zwrotne zdarzeń związane z tą interakcją.
- Czas przetwarzania, który obejmuje czas potrzebny na wykonanie wywołań zwrotnych zdarzeń.
- Opóźnienie wyświetlania, czyli czas, jaki upływa, zanim przeglądarka wyświetli kolejną klatkę zawierającą wizualny wynik interakcji.
Suma tych 3 części to całkowity czas oczekiwania na interakcję. Każda część interakcji ma wpływ na całkowite opóźnienie interakcji, dlatego ważne jest, aby wiedzieć, jak zoptymalizować każdą część interakcji, aby trwał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 wprowadzaniu danych. W zależności od innych działań na stronie opóźnienia wprowadzania mogą być znaczne. Może to być spowodowane aktywnością w głównym wątku (być może z powodu wczytywania, analizowania i kompilowania skryptów), obsługą pobierania, funkcjami timera lub innymi interakcjami, które występują w szybkiej kolejności i nakładają się na siebie.
Niezależnie od źródła opóźnienia wejściowego interakcji warto zminimalizować to opóźnienie, aby interakcje mogły jak najszybciej uruchamiać wywołania zwrotne zdarzeń.
Zależność między oceną skryptu a długimi zadaniami podczas uruchamiania
Kluczowym aspektem interaktywności w cyklu życia strony jest etap uruchamiania. Podczas wczytywania strona jest początkowo renderowana, ale pamiętaj, że samo wyrenderowanie strony nie oznacza, że wczytywanie zostało zakończone. W zależności od tego, ile zasobów jest potrzebnych do pełnego działania strony, użytkownicy mogą próbować wchodzić z nią w interakcję, gdy jest ona jeszcze wczytywana.
Jednym z czynników, które mogą wydłużyć opóźnienie danych wejściowych interakcji podczas ładowania strony, jest ocena skryptu. Po pobraniu pliku JavaScript z sieci przeglądarka musi jeszcze wykonać pewne czynności, zanim będzie można uruchomić ten kod. Obejmują one przeanalizowanie 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 spowodować długotrwałe zadania w wątku głównym, co opóźni reakcję przeglądarki na inne interakcje użytkownika. Aby strona reagowała na działania użytkownika podczas ładowania, warto wiedzieć, co można zrobić, aby zmniejszyć prawdopodobieństwo wystąpienia długich zadań podczas ładowania strony i zapewnić jej szybkie działanie.
Optymalizacja wywołań zwrotnych zdarzeń
Opóźnienie przy pierwszym działaniu 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 zakończyć się jak najszybciej.
Często przekazuj kontrolę do wątku głównego
Najlepsza ogólna rada dotycząca optymalizacji wywołań zwrotnych zdarzeń to wykonywanie w nich jak najmniejszej liczby działań. Logika interakcji może być jednak złożona i możesz być w stanie tylko nieznacznie ograniczyć wykonywaną przez nie pracę.
Jeśli tak jest w przypadku Twojej witryny, możesz spróbować podzielić pracę w wywołaniach zwrotnych zdarzeń na osobne zadania. Zapobiega to przekształceniu się pracy zbiorowej w długie zadanie, które blokuje wątek główny, co pozwala na szybsze uruchamianie innych interakcji, które w przeciwnym razie musiałyby czekać na wątek główny.
setTimeout to jeden ze sposobów dzielenia zadań, ponieważ przekazane do niego wywołanie zwrotne jest wykonywane w nowym zadaniu. Możesz używać setTimeout samodzielnie lub wyodrębnić jego użycie do osobnej funkcji w celu bardziej ergonomicznego zwracania wartości.
Bezwarunkowe przekazywanie sterowania jest lepsze niż brak przekazywania, ale istnieje bardziej subtelny sposób przekazywania sterowania do głównego wątku. Polega on na przekazywaniu sterowania tylko bezpośrednio po wywołaniu zwrotnej funkcji obsługi zdarzeń, która aktualizuje interfejs użytkownika, aby logika renderowania mogła działać szybciej.
Zezwól na wcześniejsze renderowanie
Bardziej zaawansowana technika przekazywania sterowania polega na takim skonstruowaniu kodu w wywołaniach zwrotnych zdarzeń, aby ograniczyć wykonywanie tylko do logiki wymaganej do zastosowania aktualizacji wizualnych w przypadku następnej klatki. Wszystkie inne kwestie można odłożyć na później. Dzięki temu wywołania zwrotne są lekkie i szybkie, a także skracają czas renderowania interakcji, ponieważ aktualizacje wizualne nie blokują kodu 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 ortograficznych i inne ważne informacje wizualne). Aplikacja może też zapisywać to, co piszesz, aby po powrocie do niej nie utracić żadnych danych.
W tym przykładzie w odpowiedzi na znaki wpisane przez użytkownika muszą nastąpić te 4 rzeczy: Przed wyświetleniem następnej klatki należy jednak wykonać tylko pierwszy element.
- Zaktualizuj pole tekstowe o tekst wpisany przez użytkownika i zastosuj wymagane formatowanie.
- Zaktualizuj część interfejsu, w której wyświetla się bieżąca liczba słów.
- Uruchom logikę, aby sprawdzić, czy nie ma błędów ortograficznych.
- 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 odłożenie wszystkich niekrytycznych aktualizacji do czasu po następnej klatce może skrócić czas przetwarzania, a tym samym ogólny czas oczekiwania na interakcję.
Użycie setTimeout() w wywołaniu requestAnimationFrame() w poprzednim przykładzie kodu jest nieco ezoteryczne, ale to skuteczna metoda, która działa we wszystkich przeglądarkach i zapobiega blokowaniu następnej klatki przez kod o mniejszym znaczeniu.
Unikaj nadmiernego renderowania układu
Wstrząs układu (czasami nazywany wymuszonym synchronicznym układem) to problem z wydajnością renderowania, w którym układ występuje synchronicznie. Dzieje się tak, gdy aktualizujesz style w JavaScript, a następnie odczytujesz je w tym samym zadaniu. W JavaScript jest wiele właściwości, które mogą powodować thrashing układu.
Wstrząsanie układem to wąskie gardło wydajności, ponieważ aktualizując style, a następnie natychmiast żądając wartości tych stylów w JavaScript, przeglądarka jest zmuszona do synchronicznego wykonywania pracy związanej z układem, z którą mogłaby poczekać i wykonać ją asynchronicznie później, po zakończeniu działania wywołań zwrotnych zdarzeń.
Minimalizowanie opóźnienia prezentacji
Opóźnienie prezentacji interakcji obejmuje okres od zakończenia działania wywołań zwrotnych zdarzenia interakcji do momentu, w którym przeglądarka może wyrenderować kolejną klatkę, która pokazuje wynikające z tego zmiany wizualne.
Minimalizuj rozmiar DOM
Gdy DOM strony jest mały, renderowanie zwykle kończy się szybko. Gdy jednak DOM-y stają się bardzo duże, praca związana z renderowaniem zwykle rośnie wraz z rozmiarem DOM-u. Związek między pracą związaną z renderowaniem a rozmiarem DOM nie jest liniowy, ale duże DOM wymagają więcej pracy 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żą czas potrzebny przeglądarce na wyświetlenie kolejnej klatki.
Pamiętaj, że w niektórych przypadkach nie można znacząco zmniejszyć rozmiaru dużych DOM-ów. Istnieją metody zmniejszania rozmiaru DOM, takie jak spłaszczanie DOM czy dodawanie elementów do DOM podczas interakcji użytkownika, aby utrzymać mały rozmiar początkowego DOM. Jednak te techniki mogą nie wystarczyć.
Używanie elementu 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 w praktyce polega na leniwym renderowaniu elementów w miarę zbliżania się do widocznego obszaru. Skuteczne korzystanie z content-visibility może wymagać pewnej wprawy, ale warto się tego nauczyć, jeśli dzięki temu czas renderowania będzie krótszy, co może poprawić wartość INP strony.
Zwróć uwagę na koszty wydajności podczas renderowania kodu HTML za pomocą JavaScriptu
Tam, gdzie jest HTML, jest też jego analiza. Po zakończeniu analizy HTML i przekształceniu go w DOM przeglądarka musi zastosować do niego style, przeprowadzić 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 w częściach. Przeglądarka optymalizuje sposób obsługi strumienia, stopniowo analizując jego fragmenty w miarę ich docierania i wyświetlając je po kolei. Jest to optymalizacja wydajności, ponieważ przeglądarka okresowo i automatycznie ustępuje podczas wczytywania strony, a Ty zyskujesz to bezpłatnie.
Pierwsza wizyta w dowolnej witrynie zawsze wiąże się z pewną ilością kodu HTML. Powszechnym podejściem jest jednak rozpoczęcie od minimalnej początkowej ilości kodu HTML, a następnie użycie JavaScriptu do wypełnienia obszaru treści. Kolejne aktualizacje tego obszaru treści również są wynikiem interakcji użytkownika. Jest to zwykle nazywane modelem aplikacji jednostronicowej. Jedną z wad tego wzorca jest to, że renderowanie kodu HTML za pomocą JavaScriptu po stronie klienta wiąże się nie tylko z kosztem przetwarzania JavaScriptu w celu utworzenia tego kodu HTML, ale także z tym, że przeglądarka nie będzie działać, dopóki nie zakończy analizowania i renderowania tego kodu HTML.
Pamiętaj jednak, że nawet witryny, które nie są aplikacjami SPA, prawdopodobnie będą w pewnym stopniu renderować HTML za pomocą JavaScriptu w wyniku interakcji. Zwykle nie stanowi to problemu, o ile nie renderujesz na kliencie dużych ilości kodu HTML, co może opóźnić wyświetlenie następnej klatki. Warto jednak poznać wpływ tego podejścia do renderowania kodu HTML w przeglądarce na wydajność oraz to, jak może ono wpływać na szybkość reakcji 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, prawdopodobnie zaczniesz znajdować inne powolne interakcje, zwłaszcza jeśli Twoja witryna zapewnia wiele interaktywnych funkcji. Będziesz musiał(a) je też zoptymalizować.
Kluczem do poprawy INP jest wytrwałość. Z czasem możesz sprawić, że Twoja strona będzie responsywna w takim stopniu, że użytkownicy będą zadowoleni z wrażeń, jakie im zapewniasz. Prawdopodobnie w miarę opracowywania nowych funkcji dla użytkowników będziesz musiał(-a) przejść ten sam proces optymalizacji interakcji z nimi. Wymaga to czasu i wysiłku, ale warto je poświęcić.
Obraz główny z Unsplash, autor: David Pisnoy, zmodyfikowany zgodnie z licencją Unsplash.