Dowiedz się, czym jest opóźnienie sygnału wejściowego, i poznaj techniki, które pozwolą Ci je zmniejszyć i poprawić interaktywność.
Interakcje w internecie to złożone zagadnienie, a każda aktywność w przeglądarce jest generowana z powodu różnych działań. Ich wspólną cechą jest jednak to, że następują opóźnienia przed uruchomieniem wywołań zwrotnych zdarzeń. Z tego przewodnika dowiesz się, czym jest opóźnienie wprowadzania danych i jak je zminimalizować, aby przyspieszyć interakcję z witryną.
Co to jest opóźnienie sygnału?
Opóźnienie wejściowe to czas od pierwszej interakcji użytkownika ze stroną – np. kliknięcia ekranu, kliknięcia myszą lub naciśnięcia klawisza – aż do rozpoczęcia wywołania zwrotnego zdarzenia. Każda interakcja zaczyna się od pewnego opóźnienia na wejściu.
Części opóźnienia wprowadzania danych są nieuniknione. System operacyjny zawsze potrzebuje trochę czasu na rozpoznanie zdarzenia wejściowego i przekazanie go do przeglądarki. Jednak taka część opóźnienia wprowadzania danych często jest nawet niezauważalna, a na stronie występują też inne czynniki, które mogą powodować opóźnienia na tyle długie, aby powodować problemy.
Co zrobić o opóźnieniu wprowadzania
Ogólnie rzecz biorąc, każda część interakcji powinna być jak najkrótsza, aby witryna miała jak największe szanse na osiągnięcie progu „dobrej” interakcji z następnym wyrenderowaniem (INP), niezależnie od urządzenia użytkownika. Kontrola opóźnienia sygnału to tylko jeden z elementów osiągnięcia tego progu.
Być może zastanawiasz się, czy warto sprawdzić wartości progowe opóźnienia przy pierwszym działaniu (FID), aby określić, na jakie opóźnienia mogą wystąpić sygnały wejściowe. Jednak próg „dobrego” dla FID wynosi 100 milisekund lub mniej. Jeśli przekroczysz ten próg, przeznaczysz połowę budżetu na samo opóźnienie danych wejściowych. Jest to niezalecane, jeśli uważasz, że interakcja wymaga też czasu na wywołanie zwrotne zdarzenia i wyświetlenie przez przeglądarkę następnej klatki.
Aby osiągnąć „dobry” próg INP, należy dążyć do jak najkrótszego opóźnienia sygnału, ale nie należy oczekiwać jego całkowitego wyeliminowania, ponieważ jest to niemożliwe. Jeśli nie chcesz wykonywać zbyt wielu zadań z wątkiem głównym, gdy użytkownicy próbują wchodzić w interakcję z Twoją stroną, opóźnienie wprowadzania powinno być na tyle małe, aby uniknąć problemów.
Jak zminimalizować opóźnienie sygnału
Jak już wspomnieliśmy, pewnego opóźnienia nie da się uniknąć, ale z drugiej strony można je uniknąć. Oto kilka rzeczy, które warto wziąć pod uwagę, jeśli masz problemy z dużymi opóźnieniami w wprowadzaniu danych.
Nie używaj powtarzających się minutników, które uruchamiają nadmierną pracę w wątku głównym.
W języku JavaScript są dwie często używane funkcje licznika czasu, które mogą przyczyniać się do opóźnienia danych wejściowych: setTimeout
i setInterval
. Różnica między nimi polega na tym, że setTimeout
zaplanuje wywołanie zwrotne po określonym czasie. setInterval
natomiast zaplanuje wywołanie zwrotne, które będzie wykonywane bezterminowo co n milisekund lub do momentu zatrzymania licznika za pomocą przycisku clearInterval
.
Usługa setTimeout
sama w sobie nie stanowi problemu – może pomagać w unikaniu długich zadań. Zależy to jednak od tego, kiedy przekroczono limit czasu oczekiwania i czy użytkownik spróbuje wejść w interakcję ze stroną po upływie limitu czasu oczekiwania na wywołanie zwrotne.
Poza tym setTimeout
może być uruchamiany w pętli lub rekurencyjnie, gdzie działa bardziej jak element setInterval
, ale najlepiej nie planować kolejnej iteracji do czasu zakończenia poprzedniej. Oznacza to, że pętla będzie przekazywała wątek główny przy każdym wywołaniu metody setTimeout
, jednak należy zadbać o to, aby wywołanie zwrotne nie powodowało nadmiernej pracy.
Funkcja setInterval
uruchamia wywołanie zwrotne w określonym przedziale czasu, więc znacznie bardziej prawdopodobne jest, że przeszkadza w interakcjach. Dzieje się tak, ponieważ w przeciwieństwie do pojedynczego wystąpienia wywołania setTimeout
, które jest jednorazowym wywołaniem zwrotnym, które może przeszkadzać w interakcji z użytkownikiem, powtarzający się charakter elementu setInterval
znacznie zwiększa prawdopodobieństwo, że przeszkodzi ono w interakcji, zwiększając w ten sposób opóźnienie interakcji.
Jeśli liczniki czasu występują w kodzie własnym, masz nad nimi kontrolę. Zastanów się, czy są one potrzebne, czy możesz zrobić wszystko, aby ograniczyć nakład pracy. Jednak liczniki czasu w skryptach innych firm to coś innego. Często nie masz kontroli nad działaniem zewnętrznego skryptu, a rozwiązywanie problemów z wydajnością kodu zewnętrznego wiąże się często z współpracą z zainteresowanymi osobami w celu określenia, czy dany skrypt zewnętrzny jest potrzebny. Jeśli tak, skontaktuj się z tym dostawcą, by ustalić, co można zrobić w celu rozwiązania problemów z wydajnością, jakie mogą powodować w witrynie.
Unikaj długich zadań
Jednym ze sposobów na uniknięcie dużych opóźnień związanych z wprowadzaniem danych jest unikanie długich zadań. Jeśli nadmierna ilość pracy z wątkiem głównym blokuje ten wątek podczas interakcji, zwiększy to opóźnienie danych wejściowych, zanim nastąpi zakończenie długich zadań.
Poza ograniczeniem ilości pracy wykonywanej przez użytkownika (i zawsze staraj się robić jak najmniejszą ilość pracy w wątku głównym), możesz poprawić reagowanie na działania użytkowników przez dzielenie długich zadań.
Zwróć uwagę na pokrywanie się interakcji
Szczególnie trudnym aspektem optymalizacji INP może być sytuacja, w której występują interakcje, które nakładają się na siebie. Pokrywanie się interakcji oznacza, że po interakcji z jednym elementem inicjujesz kolejną interakcję ze stroną, zanim początkowa interakcja mogła wyrenderować następną klatkę.
Źródła interakcji mogą być tak proste, jak użytkownicy wykonujący wiele interakcji w krótkim czasie. Może się tak zdarzyć, gdy użytkownicy wpisują pola formularza, które w krótkim czasie mogą wymagać wielu interakcji z klawiatury. Jeśli praca nad kluczowym zdarzeniem jest szczególnie kosztowna – na przykład w częstym przypadku pól autouzupełniania, w których żądania sieciowe są wysyłane do backendu, masz kilka możliwości:
- Rozważ odrzucenie danych wejściowych, aby ograniczyć liczbę wywołań zwrotnych zdarzenia w danym okresie.
AbortController
pozwala anulować wychodzące żądaniafetch
, aby wątek główny nie przeciążył się obsługą wywołań zwrotnychfetch
. Uwaga: właściwościsignal
instancjiAbortController
może też służyć do przerywania zdarzeń.
Innym źródłem zwiększonego opóźnienia wprowadzania z powodu nakładających się interakcji mogą być drogie animacje. Animacje w języku JavaScript mogą w szczególności uruchamiać wiele wywołań requestAnimationFrame
, które mogą przeszkadzać użytkownikom w interakcjach. Aby obejść ten problem, używaj animacji CSS, gdy tylko jest to możliwe. Pozwoli to uniknąć kolejki potencjalnie drogich klatek animacji. Jeśli jednak to zrobisz, unikaj nieskomponowanych animacji, aby były one uruchamiane głównie w wątkach GPU i kompozytora, a nie w wątku głównym.
Podsumowanie
Chociaż opóźnienia wprowadzania danych mogą nie odpowiadać większości czasu na przetworzenie interakcji, pamiętaj, że każda jej część może zająć sporo czasu, który możesz zredukować. Jeśli obserwujesz duże opóźnienie wprowadzania danych, możesz je zmniejszyć. Unikanie powtarzających się wywołań zwrotnych licznika czasu, dzielenie długich zadań i świadomość potencjalnego pokrywania się interakcji mogą pomóc zredukować opóźnienie wprowadzania, co z kolei przełoży się na szybszą interaktywność użytkowników witryny.
Baner powitalny z albumu Unsplash autorstwa Erika Mcleana.