Duże rozmiary DOM mają większy wpływ na interaktywność, niż mogłoby się wydawać. Z tego przewodnika dowiesz się, dlaczego tak się dzieje i co możesz zrobić.
Nie da się tego uniknąć: gdy tworzysz stronę internetową, ma ona obiektowy model dokumentu (DOM). DOM reprezentuje strukturę kodu HTML strony i umożliwia JavaScriptowi oraz CSS dostęp do struktury i zawartości strony.
Problem polega jednak na tym, że rozmiar DOM wpływa na zdolność przeglądarki do szybkiego i wydajnego renderowania strony. Ogólnie rzecz biorąc, im większy jest DOM, tym droższe jest początkowe renderowanie strony i późniejsze aktualizowanie renderowania w trakcie cyklu życia strony.
Staje się to problematyczne na stronach z bardzo dużym modelem DOM, gdy interakcje, które modyfikują lub aktualizują model DOM, wywołują kosztowne operacje układu, które wpływają na zdolność strony do szybkiego reagowania. Kosztowne operacje układu mogą wpływać na czas od interakcji do kolejnego wyrenderowania (INP). Jeśli chcesz, aby strona szybko reagowała na interakcje użytkownika, zadbaj o to, aby rozmiary DOM były tylko tak duże, jak to konieczne.
Kiedy DOM strony jest zbyt duży?
Według Lighthouse rozmiar DOM strony jest nadmierny, gdy przekracza 1400 węzłów. Lighthouse zacznie wyświetlać ostrzeżenia, gdy DOM strony przekroczy 800 węzłów. Weźmy na przykład ten kod HTML:
<ul>
<li>List item one.</li>
<li>List item two.</li>
<li>List item three.</li>
</ul>
W powyższym kodzie znajdują się 4 elementy DOM: element <ul>
i jego 3 elementy podrzędne <li>
. Twoja strona internetowa będzie prawie na pewno zawierać znacznie więcej węzłów, dlatego ważne jest, aby wiedzieć, co możesz zrobić, aby kontrolować rozmiar DOM, a także jakie inne strategie optymalizacji renderowania możesz zastosować, gdy rozmiar DOM strony będzie już najmniejszy z możliwych.
Jak duże DOM-y wpływają na wydajność strony?
Duże DOM-y wpływają na wydajność strony na kilka sposobów:
- podczas początkowego renderowania strony. Gdy do strony zostanie zastosowany arkusz CSS, powstanie struktura podobna do DOM, zwana modelem obiektów CSS (CSSOM). W miarę wzrostu szczegółowości selektorów CSS model CSSOM staje się bardziej złożony, a wykonanie niezbędnych operacji związanych z układem, stylem, kompozycją i rysowaniem, które są potrzebne do wyświetlenia strony internetowej na ekranie, zajmuje więcej czasu. Dodatkowa praca zwiększa czas oczekiwania na interakcje, które występują na wczesnym etapie wczytywania strony.
- Gdy interakcje modyfikują DOM, np. przez wstawianie lub usuwanie elementów albo modyfikowanie zawartości i stylów DOM, praca niezbędna do wyrenderowania tej aktualizacji może skutkować bardzo kosztownym układem, stylizacją, komponowaniem i rysowaniem. Podobnie jak w przypadku początkowego renderowania strony, zwiększenie specyficzności selektora CSS może zwiększyć nakład pracy związany z renderowaniem, gdy elementy HTML są wstawiane do DOM w wyniku interakcji.
- Gdy JavaScript wysyła zapytania do DOM, odwołania do elementów DOM są przechowywane w pamięci. Jeśli na przykład wywołasz funkcję
document.querySelectorAll
, aby wybrać wszystkie elementy<div>
na stronie, koszt pamięci może być znaczny, jeśli wynik zwróci dużą liczbę elementów DOM.
Wszystkie te czynniki mogą wpływać na interaktywność, ale szczególnie ważny jest drugi element z powyższej listy. Jeśli interakcja powoduje zmianę w DOM, może to wywołać wiele działań, które mogą przyczynić się do niskiego wyniku INP na stronie.
Jak zmierzyć rozmiar DOM?
Rozmiar DOM możesz zmierzyć na kilka sposobów. Pierwsza metoda korzysta z Lighthouse. Po przeprowadzeniu audytu statystyki dotyczące DOM bieżącej strony znajdą się w audycie „Unikaj nadmiernego rozmiaru DOM” w sekcji „Diagnostyka”. W tej sekcji możesz zobaczyć łączną liczbę elementów DOM, element DOM zawierający najwięcej elementów podrzędnych oraz element DOM o największej głębokości.
Prostsza metoda polega na użyciu konsoli JavaScript w narzędziach dla programistów w dowolnej popularnej przeglądarce. Aby uzyskać łączną liczbę elementów HTML w DOM, po wczytaniu strony możesz użyć w konsoli tego kodu:
document.querySelectorAll('*').length;
Jeśli chcesz zobaczyć aktualizację rozmiaru DOM w czasie rzeczywistym, możesz też użyć narzędzia do monitorowania wydajności. Za pomocą tego narzędzia możesz powiązać operacje związane z układem i stylem (oraz inne aspekty wydajności) z bieżącym rozmiarem DOM.
Jeśli rozmiar DOM zbliża się do progu ostrzegawczego rozmiaru DOM w Lighthouse lub go przekracza, następnym krokiem jest zmniejszenie rozmiaru DOM, aby poprawić zdolność strony do reagowania na interakcje użytkowników i zwiększyć INP witryny.
Jak mogę zmierzyć liczbę elementów DOM, na które wpływa interakcja?
Jeśli w warunkach laboratoryjnych profilujesz powolną interakcję, która Twoim zdaniem może mieć związek z rozmiarem DOM strony, możesz sprawdzić, ile elementów DOM zostało objętych działaniem. Aby to zrobić, wybierz w profilerze dowolną aktywność oznaczoną jako „Recalculate Style” (Ponowne obliczanie stylu) i obserwuj dane kontekstowe w dolnym panelu.
Na powyższym zrzucie ekranu widać, że po wybraniu ponownego obliczenia stylu elementu „work” wyświetla się liczba elementów, których to dotyczy. Powyższy zrzut ekranu przedstawia ekstremalny przypadek wpływu rozmiaru DOM na renderowanie na stronie z wieloma elementami DOM. Te informacje diagnostyczne są jednak przydatne w każdym przypadku, aby określić, czy rozmiar DOM jest czynnikiem ograniczającym czas potrzebny na wyrenderowanie kolejnej klatki w odpowiedzi na interakcję.
Jak mogę zmniejszyć rozmiar DOM?
Oprócz sprawdzania kodu HTML witryny pod kątem niepotrzebnych znaczników głównym sposobem na zmniejszenie rozmiaru DOM jest zmniejszenie jego głębokości. Sygnałem, że DOM może być niepotrzebnie głęboki, jest widoczny w narzędziach dla programistów w przeglądarce na karcie Elementy kod, który wygląda mniej więcej tak:
<div>
<div>
<div>
<div>
<!-- Contents -->
</div>
</div>
</div>
</div>
Gdy widzisz takie wzorce, możesz je prawdopodobnie uprościć, spłaszczając strukturę DOM. Zmniejszy to liczbę elementów DOM i prawdopodobnie pozwoli uprościć style strony.
Głębokość DOM może być też objawem używanych przez Ciebie frameworków. W szczególności frameworki oparte na komponentach, takie jak te, które korzystają z JSX, wymagają zagnieżdżania wielu komponentów w kontenerze nadrzędnym.
Wiele frameworków umożliwia jednak uniknięcie zagnieżdżania komponentów dzięki użyciu tzw. fragmentów. Do platform opartych na komponentach, które oferują fragmenty jako funkcję, należą między innymi:
Używając fragmentów w wybranym frameworku, możesz zmniejszyć głębokość DOM. Jeśli obawiasz się, że spłaszczenie struktury DOM wpłynie na stylizację, możesz skorzystać z nowocześniejszych (i szybszych) trybów układu, takich jak flexbox lub grid.
Inne strategie do rozważenia
Nawet jeśli starasz się spłaszczyć drzewo DOM i usunąć niepotrzebne elementy HTML, aby było jak najmniejsze, może ono nadal być dość duże i powodować wiele pracy związanej z renderowaniem, gdy zmienia się w odpowiedzi na interakcje użytkownika. Jeśli znajdziesz się w takiej sytuacji, możesz zastosować inne strategie, aby ograniczyć pracę związaną z renderowaniem.
Rozważ podejście addytywne
Może się zdarzyć, że duże części strony nie będą początkowo widoczne dla użytkownika podczas pierwszego renderowania. Może to być okazja do leniwego ładowania kodu HTML przez pomijanie tych części DOM podczas uruchamiania, ale dodawanie ich, gdy użytkownik wchodzi w interakcję z częściami strony, które wymagają początkowo ukrytych aspektów strony.
To podejście jest przydatne zarówno podczas początkowego wczytywania, jak i później. Podczas początkowego wczytywania strony wykonujesz mniej pracy związanej z renderowaniem, co oznacza, że początkowy ładunek HTML będzie mniejszy i szybciej się renderuje. Dzięki temu interakcje w tym kluczowym okresie będą miały większe szanse na uruchomienie przy mniejszej konkurencji o uwagę głównego wątku.
Jeśli wiele części strony jest początkowo ukrytych, może to również przyspieszyć inne interakcje, które powodują ponowne renderowanie. Jednak w miarę jak inne interakcje będą dodawać kolejne elementy do DOM, praca związana z renderowaniem będzie się zwiększać wraz z rozwojem DOM w trakcie cyklu życia strony.
Dodawanie elementów do DOM w miarę upływu czasu może być trudne i ma swoje wady. Jeśli wybierzesz tę metodę, prawdopodobnie będziesz wysyłać żądania sieciowe, aby pobrać dane do wypełnienia kodu HTML, który chcesz dodać do strony w odpowiedzi na interakcję użytkownika. Trwające żądania sieciowe nie są uwzględniane w INP, ale mogą zwiększać postrzegane opóźnienie. Jeśli to możliwe, wyświetlaj wskaźnik ładowania lub inny sygnał, że dane są pobierane, aby użytkownicy wiedzieli, że coś się dzieje.
Ograniczanie złożoności selektora CSS
Gdy przeglądarka analizuje selektory w arkuszu CSS, musi przejść przez drzewo DOM, aby zrozumieć, jak i czy te selektory mają zastosowanie do bieżącego układu. Im bardziej złożone są te selektory, tym więcej pracy musi wykonać przeglądarka, aby przeprowadzić zarówno wstępne renderowanie strony, jak i zwiększone ponowne obliczanie stylów oraz pracę związaną z układem, jeśli strona zmieni się w wyniku interakcji.
Użyj usługi content-visibility
CSS udostępnia właściwość content-visibility
, która umożliwia odroczone renderowanie elementów DOM niewyświetlanych na ekranie. Gdy elementy zbliżają się do obszaru widocznego, są renderowane na żądanie. Korzyści z content-visibility
nie tylko znacznie zmniejszają ilość pracy związanej z renderowaniem podczas początkowego renderowania strony, ale także pomijają renderowanie elementów poza ekranem, gdy DOM strony zmienia się w wyniku interakcji użytkownika.
Podsumowanie
Zmniejszenie rozmiaru DOM do niezbędnego minimum to dobry sposób na optymalizację INP witryny. Dzięki temu możesz skrócić czas potrzebny przeglądarce na wykonanie pracy związanej z układem i renderowaniem po zaktualizowaniu DOM. Nawet jeśli nie możesz znacząco zmniejszyć rozmiaru DOM, możesz zastosować techniki, które pozwolą Ci ograniczyć renderowanie do poddrzewa DOM, np. za pomocą funkcji CSS containment i właściwości CSS content-visibility
.
Niezależnie od tego, jak to zrobisz, stworzenie środowiska, w którym renderowanie jest zminimalizowane, a także zmniejszenie ilości pracy związanej z renderowaniem, jaką wykonuje strona w odpowiedzi na interakcje, sprawi, że witryna będzie bardziej responsywna dla użytkowników. Oznacza to, że Twoja witryna będzie miała niższy wskaźnik INP, co przełoży się na lepsze wrażenia użytkowników.