Zmniejszenie czasu wczytywania o 30 razy i przejście na Next.js pomogło The Economic Times zmniejszyć współczynnik INP prawie 4-krotnie, co przełożyło się na spadek współczynnika odrzuceń o 50% i wzrost liczby wyświetleń o 43%.
Czas od interakcji do kolejnego wyrenderowania (INP) to dane, które oceniają responsywność witryny na dane wprowadzane przez użytkownika. Dobra responsywność oznacza, że strona szybko reaguje na interakcje użytkowników. Im niższa wartość INP strony, tym lepiej reaguje ona na interakcje użytkowników.
Niewyraźny początek
Gdy firma Google wprowadziła INP jako eksperymentalne dane, które mogą przekształcić się w jeden z podstawowych wskaźników internetowych, zespół Ekonomii podjął wyzwanie, aby rozwiązać ten problem, zanim doszedł do poziomu 1. Zapewnienie użytkownikom najwyższej jakości usług jest kluczowe dla naszych podstawowych wartości biznesowych.
INP jest jednym z najtrudniejszych do rozwiązania wskaźników. Na początku nie było jasne, jak skutecznie mierzyć INP. Utrudniał to brak wsparcia ze strony społeczności – w przypadku większości dostawców usług monitorowania użytkowników realnych (RUM), którzy jeszcze go nie obsługiwali. Mieliśmy jednak narzędzia Google RUM, takie jak Raport na temat użytkowania Chrome (CrUX), web-vitals
bibliotek JavaScript i inne narzędzia pomocnicze, które dawały nam pewien obraz sytuacji, gdy analizowaliśmy dalsze działania. Na początku nasz INP wynosił prawie 1000 ms na poziomie źródła.
Podczas korygowania INP w warunkach rzeczywistych okazało się, że jednym z wskaźników laboratoryjnych, na które można się kierować, może być Total Blocking Time (TBT). TBT było już dobrze udokumentowane i obsługiwane przez społeczność. Mimo że spełnialiśmy już progi dotyczące podstawowych wskaźników internetowych, nie osiągnęliśmy tak dobrych wyników w przypadku czasu wczytywania strony, który na początku wynosił ponad 3 sekundy.
Czym jest TBT i jakie działania podjęliśmy, aby go ulepszyć?
TBT to dane laboratoryjne, które służą do pomiaru responsywności strony internetowej na dane wprowadzane przez użytkownika podczas jej wczytywania. Każde zadanie, którego wykonanie zajmuje ponad 50 ms, jest uważane za długie zadanie, a czas po przekroczeniu progu 50 ms jest nazywany czasem blokowania.
Do ustalenia czasu pracy obliczono sumę czasu blokowania wszystkich długich zadań podczas wczytywania strony. Jeśli na przykład podczas wczytywania występują 2 długie zadania, czas blokowania jest określany w ten sposób:
- Zadanie A zajmuje 80 milisekund (o 30 milisekund dłużej niż 50 milisekund).
- Zadanie B zajmuje 100 milisekund (o 50 milisekund dłużej niż 50 milisekund).
TBT strony wyniesie 80 ms (30 + 50). Im niższa wartość TBT, tym lepiej. TBT dobrze koreluje z INP.
Oto krótkie porównanie TBT przed i po wprowadzeniu zmian:
Minimalizowanie pracy z wątkiem głównym
Główny wątek przeglądarki obsługuje wszystko, od analizowania kodu HTML, tworzenia DOM do analizowania kodu CSS i zastosowywania stylów, a także interpretowania i wykonywania kodu JavaScript. Główny wątek obsługuje też interakcje z użytkownikiem, czyli kliknięcia, dotknięcia i naciśnięcia klawiszy. Jeśli wątek główny jest zajęty wykonywaniem innych zadań, może nie reagować efektywnie na dane wejściowe użytkownika, co może powodować problemy.
Było to dla nas najtrudniejsze zadanie, ponieważ mamy własne algorytmy do wykrywania tożsamości użytkownika na potrzeby wyświetlania reklam na podstawie stanu subskrypcji oraz skrypty innych firm do testów A/B, analizy danych itp.
Na początku wprowadziliśmy drobne zmiany, np. obniżyliśmy priorytet wczytywania mniej istotnych zasobów biznesowych. Po drugie, do niekrytycznych zadań użyliśmy requestIdleCallback
, co może pomóc w ograniczeniu czasu oczekiwania na odpowiedź.
if ('requestIdleCallback' in window) {
this.requestIdleCallbackId = requestIdleCallback(fetchMarketsData.bind(this), {timeout: 3000});
} else {
fetchMarketsData(); // Fallback in case requestIdleCallback is not supported
}
W przypadku użycia funkcji requestIdleCallback
zalecamy określenie limitu czasu, ponieważ dzięki temu, jeśli po upływie określonego czasu wywołanie zwrotne nie zostanie jeszcze wykonane, zostanie ono wykonane natychmiast po upływie limitu czasu.
Minimalizowanie czasu oceny skryptu
Biblioteki innych firm zostały też ładowane leniwie za pomocą komponentów z możliwością wczytania. Usunęliśmy też nieużywany kod JavaScript i CSS, wykonując profilowanie strony za pomocą narzędzia do pomiaru pokrycia kodu w Narzędziach deweloperskich Chrome. Pomagało nam to zidentyfikować obszary, w których potrzebne było tree shaking, aby zmniejszyć ilość kodu podczas wczytywania strony, a tym samym zredukować początkowy rozmiar pakietu aplikacji.
Zmniejsz rozmiar DOM
Według Lighthouse duże rozmiary DOM zwiększają wykorzystanie pamięci, wydłużają czas przeliczania stylów i powodują kosztowne przeformatowania układu.
Zmniejszyliśmy liczbę węzłów DOM na 2 sposoby:
- Najpierw renderowaliśmy elementy menu na żądanie użytkownika (po kliknięciu). Zmniejszyło to rozmiar DOM-u o około 1200 węzłów.
- Po drugie, zoptymalizowaliśmy ładowanie mniej ważnych widżetów.
Dzięki tym wszystkim działaniom udało nam się znacznie zmniejszyć TBT, a nasz INP zmniejszył się odpowiednio o prawie 50%:
W tym momencie prawie zabrakło nam łatwych wygranych, które pozwoliły nam jeszcze bardziej ograniczyć TBT (i INP z serwera proxy), ale wiedzieliśmy, że mamy dużo możliwości poprawy. Wtedy postanowiliśmy uaktualnić nasz niestandardowy szablon interfejsu użytkownika do najnowszej wersji Reacta oraz Next.js, aby lepiej korzystać z haków i uniknąć niepotrzebnego ponownego renderowania komponentów.
Ze względu na częstsze aktualizacje i stosunkowo mniejszy ruch w porównaniu z innymi częściami witryny zaczęliśmy przenosić strony tematyczne do Next.js. Wykorzystaliśmy też PartyTown w celu przekazania robotom internetowym dodatkowej pracy z wątkami głównymi oraz techniki takie jak requestIdleCallBack
do odroczenia niekrytycznych zadań.
Jak ulepszone INP pomogło The Economic Times?
Obecne TBT i INP w miejscu początkowym
W chwili opublikowania tego posta czas oczekiwania na uruchomienie dla strony początkowej wynosił 120 milisekund, czyli mniej niż 3260 milisekund w momencie rozpoczęcia prac optymalizacyjnych. Po optymalizacji czas INP dla naszego źródła wynosił 257 ms (wcześniej ponad 1000 ms).
Trend INP CrUX
Ruch na stronach tematów stanowi znacznie mniejszą część całego ruchu. Dlatego było to idealne miejsce na eksperymentowanie. Wyniki CrUX i wyniki biznesowe były bardzo zachęcające, więc postanowiliśmy zwiększyć nasze wysiłki na całej stronie, aby odnieść jeszcze większe korzyści.
Analiza TBT Akamai mPulse
Jako rozwiązanie RUM używamy Akamai mPulse, które mierzy TBT w polu. Zauważyliśmy stały spadek wartości TBT, co wyraźnie wskazuje na wyniki naszych działań mających na celu zmniejszenie INP. Jak widać na zrzucie ekranu poniżej, wartości TBT spadły z około 5 sekund do około 200 milisekund w terenie.
Wynik biznesowy
Ogólnie nasze działania mające na celu zmniejszenie wartości TBT o 30 razy, a także przejście na Next.js pomogły nam zmniejszyć wartość INP prawie 4-krotnie, co ostatecznie doprowadziło do obniżenia współczynnika odrzuceń o 50% i wzrostu liczby wyświetleń stron o 43% na stronach tematycznych.
Podsumowanie
Podsumowując, organizacja INP bardzo pomogła w znalezieniu problemów z wydajnością w czasie działania w niektórych częściach witryny The Times. Wykazano, że jest to jeden z najskuteczniejszych wskaźników wpływających pozytywnie na wyniki biznesowe. Ze względu na bardzo zachęcające wyniki, które uzyskaliśmy dzięki tym działaniom, chcemy zwiększyć skalę optymalizacji w innych obszarach naszej witryny i uzyskać dodatkowe korzyści.