Zmniejszenie czasu wczytywania o 30 razy i przejście na Next.js pomogły 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ń stron 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.
Niejasny początek
Gdy Google wprowadził INP jako dane eksperymentalne, które mogą stać się jednym z podstawowych wskaźników internetowych, zespół Economic Times podjął się wyzwania, aby je poprawić, zanim staną się jednym z podstawowych wskaźników internetowych, ponieważ zapewnienie użytkownikom wrażeń na światowym poziomie jest kluczowe dla naszych podstawowych wartości biznesowych.
INP było do tej pory jednym z najtrudniejszych do rozwiązania wskaźników. Na początku nie było jasne, jak skutecznie mierzyć INP. Utrudnieniem było brak wsparcia społeczności, w tym większości dostawców usług monitorowania użytkowników rzeczywistych (RUM), którzy nie oferowali jeszcze tego rozwiązania. 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 mierzą responsywność 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.
TBT jest obliczany jako suma 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 interpretację i wykonywanie 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 zmniejszeniu 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 przekroczeniu limitu czasu.
Minimalizowanie czasu oceny skryptu
Biblioteki zewnętrzne wczytujemy też 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 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 wczytywanie 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 wyczerpaliśmy już niemal wszystkie możliwości łatwego zmniejszenia czasu ładowania strony (i w drugim rzędzie czasu ładowania strony przez pośrednika), ale wiedzieliśmy, że mamy jeszcze sporo miejsca na poprawę. 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. Użyliśmy też PartyTown, aby przekazać dodatkowe obciążenie głównego wątku procesom wątekom internetowym, a także technik takich jak requestIdleCallBack
, aby odłożyć na później zadania niekrytyczne.
Jak ulepszone INP pomogło The Economic Times?
Aktualne wartości TBT i INP na potrzeby pochodzenia
W momencie publikacji tego posta czas TBT dla naszej origin wynosił 120 ms, w porównaniu z 3260 ms na początku optymalizacji. 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 mPulse firmy Akamai
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, INP bardzo pomogło w określeniu problemów z wydajnością w czasie działania w częściach witryny Economic 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.