Jak duże rozmiary DOM wpływają na interaktywność i co można z tym zrobić

Duże rozmiary DOM mają większy wpływ na interaktywność, niż Ci się wydaje. Z tego przewodnika dowiesz się, dlaczego tak się dzieje i co możesz zrobić.

Nie ma innej możliwości: gdy tworzysz stronę internetową, ta strona będzie miała model DOM. DOM reprezentuje strukturę kodu HTML strony i daje dostęp do jej struktury oraz zawartości przez JavaScript i CSS.

Problem polega jednak na tym, że rozmiar DOM wpływa na szybkość i skuteczność renderowania strony przez przeglądarkę. Ogólnie rzecz biorąc, im większy jest DOM, tym droższe jest początkowe renderowanie strony i jej aktualizacja w późniejszym etapie cyklu życia.

Stanowi to problem na stronach z bardzo dużymi modelami DOM, gdy interakcje, które modyfikują lub aktualizują model DOM, powodują kosztowne zmiany układu, które wpływają na szybkość reakcji strony. Kosztowna praca nad układem może wpływać na czas od interakcji do kolejnego wyrenderowania (INP). Jeśli chcesz, aby strona szybko reagowała na interakcje użytkowników, zadbaj o to, aby rozmiary DOM były jak najmniejsze.

Kiedy DOM strony jest za duży?

Według Lighthouse rozmiar DOM strony jest zbyt duży, 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 kod HTML:

<ul>
  <li>List item one.</li>
  <li>List item two.</li>
  <li>List item three.</li>
</ul>

W powyższym kodzie występują 4 elementy DOM: element <ul> i 3 elementy podrzędne <li>. Twoja strona internetowa będzie prawie na pewno miała znacznie więcej węzłów, dlatego warto wiedzieć, jak kontrolować rozmiary DOM-u. Warto też poznać inne strategie optymalizacji renderowania, gdy już zminimalizujesz rozmiar DOM-u strony.

Jak duży DOM wpływa na wydajność strony?

Duże DOM-y wpływają na wydajność strony na kilka sposobów:

  1. Podczas początkowego renderowania strony. Gdy do strony zastosujesz arkusz CSS, zostanie utworzona struktura podobna do modelu DOM, zwana modelem obiektów CSS (CSSOM). Wraz ze wzrostem szczegółowości selektorów CSS, obiekt CSSOM staje się bardziej złożony, a na dokonanie niezbędnych czynności związanych z układem, stylami, kompozycją i malowaniem, które są potrzebne do wyświetlenia strony internetowej na ekranie, potrzeba więcej czasu. To dodatkowe działanie zwiększa opóźnienie interakcji, które występują na początku wczytywania strony.
  2. Gdy interakcje modyfikują DOM, np. przez wstawianie lub usuwanie elementów albo modyfikowanie zawartości i stylów DOM, konieczne do renderowania zmiany mogą wiązać się z bardzo kosztowną pracą nad układem, stylami, kompozycją i malowaniem. 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.
  3. Gdy JavaScript wysyła zapytanie 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.
Zrzut ekranu przedstawiający długie zadanie spowodowane nadmiernym renderowaniem w panelu wydajności w Narzędziach deweloperskich w Chrome Stos wywołań długiego zadania pokazuje znaczny czas poświęcony na ponowne obliczanie stylów strony oraz na wstępną obróbkę graficzną.
Długie zadanie widoczne w profilu wydajności w Narzędziach deweloperskich w Chrome. Wyświetlone długie zadanie jest spowodowane wstawianiem elementów DOM do dużego DOM za pomocą JavaScriptu.

Wszystkie te elementy mogą wpływać na interaktywność, ale drugi element na liście ma szczególne znaczenie. Jeśli interakcja powoduje zmianę DOM, może to wywołać wiele działań, które mogą przyczynić się do niskiej wartości INP na stronie.

Jak mierzyć rozmiar DOM?

Rozmiar DOM można mierzyć na kilka sposobów. Pierwsza metoda korzysta z Lighthouse. Gdy uruchomisz audyt, statystyki dotyczące DOM bieżącej strony będą widoczne w sekcji „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, a także element DOM znajdujący się najgłębiej w strukturze.

Prostszą metodą jest użycie konsoli JavaScriptu w narzędziach dla programistów w dowolnej popularnej przeglądarce. Aby poznać łączną liczbę elementów HTML w DOM, możesz użyć tego kodu w konsoli po załadowaniu strony:

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 dotyczące układu i stylu (oraz inne aspekty wydajności) z aktualnym rozmiarem DOM.

Zrzut ekranu przedstawiający monitor wydajności w Narzędziach deweloperskich w Chrome Po lewej stronie znajdują się różne aspekty skuteczności strony, które można stale monitorować przez cały okres jej istnienia. Na zrzucie ekranu widać, że aktywnie monitorowana jest liczba węzłów DOM, układów na sekundę i przeliczeń stylów na sekcję.
Monitor wydajności w Narzędziach deweloperskich w Chrome. W tym widoku bieżąca liczba węzłów DOM jest przedstawiana na wykresie wraz z operacjami układu i przeliczeniami stylów wykonywanymi na sekundę.

Jeśli rozmiar DOM zbliża się do progu ostrzeżenia dotyczącego rozmiaru DOM w Lighthouse lub nie spełnia go w ogóle, następnym krokiem będzie znalezienie sposobu na zmniejszenie rozmiaru DOM, aby zwiększyć zdolność strony do reagowania na interakcje użytkowników, co pozwoli poprawić INP witryny.

Jak mogę zmierzyć liczbę elementów DOM, na które wpływa interakcja?

Jeśli w laboratorium profilujesz wolno działającą interakcję, która według Ciebie może mieć związek z rozmiarem DOM-u strony, możesz sprawdzić, ile elementów DOM zostało dotkniętych, wybierając w profilu dowolny element aktywności oznaczony etykietą „Ponownie oblicz styl” i obserwując dane kontekstowe w dolnym panelu.

Zrzut ekranu przedstawiający wybraną aktywność związaną z przeliczaniem stylów w panelu wydajności w Narzędziach deweloperskich w Chrome U góry ścieżka interakcji pokazuje interakcję polegającą na kliknięciu, a większość pracy jest wykonywana podczas ponownego obliczania stylu i wstępnego malowania. U dołu znajduje się panel z dodatkowymi informacjami o wybranej aktywności, który informuje, że dotyczy ona 2547 elementów DOM.
Obserwowanie liczby elementów w DOM, na które wpłynęło ponowne obliczanie stylów. Zaznaczona część interakcji na ścieżce interakcji reprezentuje część czasu trwania interakcji, która trwała ponad 200 ms, co jest wyznaczonym „dobrym” progiem INP.

Na powyższym zrzucie ekranu widać, że po wybraniu ponownego obliczenia stylu pracy wyświetlana jest liczba elementów, których dotyczy zmiana. Powyższy zrzut ekranu pokazuje skrajne przypadki wpływu rozmiaru DOM na renderowanie strony zawierającej wiele elementów DOM, ale te informacje diagnostyczne są przydatne w każdym przypadku, aby określić, czy rozmiar DOM jest czynnikiem ograniczającym czas potrzebny na wyrenderowanie kolejnego klatki w odpowiedzi na interakcję.

Jak zmniejszyć rozmiar DOM?

Oprócz sprawdzenia, czy kod HTML witryny nie zawiera niepotrzebnego znacznika, głównym sposobem na zmniejszenie rozmiaru DOM jest zmniejszenie jego głębokości. Jednym z wskazówek, że DOM może być niepotrzebnie rozbudowany, jest wyświetlanie na karcie Elementy w narzędziach dla programistów w przeglądarce znaczników podobnego do tego:

<div>
  <div>
    <div>
      <div>
        <!-- Contents -->
      </div>
    </div>
  </div>
</div>

Gdy widzisz takie wzorce, możesz je uprościć, spłaszając strukturę DOM. Dzięki temu zmniejszysz liczbę elementów DOM i prawdopodobnie uda Ci się uprościć style stron.

Głębokość DOM może też być objawem używania przez Ciebie frameworków. Szczególnie frameworki oparte na komponentach, takie jak te, które korzystają z JSX, wymagają zagnieżdżania wielu komponentów w kontenerze nadrzędnym.

Jednak wiele frameworków umożliwia unikanie zagnieżdżania komponentów dzięki fragmentom. Oto niektóre frameworki oparte na komponentach, które oferują fragmenty jako funkcję:

Korzystając z fragmentów w ramach wybranej platformy, możesz zmniejszyć głębokość DOM. Jeśli niepokoisz się wpływem spłaszczenia struktury DOM na stylizację, możesz skorzystać z nowszych (i szybszych) trybów układu, takich jak flexbox czy grid.

Inne strategie do rozważenia

Nawet jeśli postarasz się spłaszczyć drzewo DOM i usunąć zbędne elementy HTML, aby zachować jak najmniejszą możliwą wielkość DOM, to nadal może ono być dość duże i wymagać dużej pracy związanej z renderowaniem, gdy zmienia się w odpowiedzi na działania użytkownika. Jeśli tak się stanie, możesz zastosować inne strategie, aby ograniczyć renderowanie.

Rozważ podejście polegające na dodawaniu

Może się zdarzyć, że podczas pierwszego renderowania strony znaczna część jej zawartości nie będzie widoczna dla użytkownika. Może to być okazja do opóźnionego wczytywania kodu HTML przez pominięcie tych części DOM podczas uruchamiania, ale dodanie ich, gdy użytkownik wejdzie w interakcję z częściami strony, które wymagają początkowo ukrytych aspektów strony.

Takie podejście jest przydatne zarówno podczas początkowego wczytywania, jak i później. Podczas wczytywania strony na początku nie trzeba wykonywać tak dużo pracy związanej z renderowaniem, co oznacza, że początkowy ładunek HTML będzie lżejszy i szybciej się renderuje. Dzięki temu w tym kluczowym okresie interakcje będą miały więcej możliwości, a inne elementy będą mniej konkurować o uwagę głównego wątku.

Jeśli masz wiele części strony, które są początkowo ukryte podczas wczytywania, może to przyspieszyć inne interakcje, które powodują ponowne renderowanie. Jednak inne interakcje zwiększają rozmiar DOM, więc podczas całego cyklu życia strony praca związana z renderowaniem będzie się zwiększać wraz z rozwojem DOM.

Dodawanie elementów do DOM-u z upływem czasu może być trudne i wymagać kompromisów. Jeśli korzystasz z tego rozwiązania, prawdopodobnie wysyłasz żądania sieci, aby pobrać dane, które mają wypełnić kod HTML, który chcesz dodać do strony w odpowiedzi na działanie użytkownika. Chociaż żądania sieci w trakcie przesyłania nie są liczone do INP, mogą zwiększać odczuwalne opóźnienie. Jeśli to możliwe, wyświetl wskaźnik ładowania lub inny wskaźnik, że dane są pobierane, aby użytkownicy wiedzieli, że coś się dzieje.

Ogranicz złożoność 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 początkowe renderowanie strony, jak i częstsze ponowne obliczanie stylów oraz pracę nad układem, jeśli strona zmienia się w wyniku interakcji.

Użyj właściwości content-visibility.

CSS udostępnia właściwość content-visibility, która jest skutecznym sposobem na opóźnione renderowanie elementów DOM niewyświetlanych na ekranie. Gdy elementy zbliżają się do widoku, są renderowane na żądanie. Zalety content-visibility to nie tylko znaczne skrócenie czasu renderowania podczas początkowego renderowania strony, ale też pominięcie renderowania elementów znajdujących się poza ekranem, gdy DOM strony zostanie zmieniony w wyniku interakcji z użytkownikiem.

Podsumowanie

Zmniejszenie rozmiaru DOM do niezbędnego minimum to dobry sposób na optymalizację INP witryny. Dzięki temu przeglądarka będzie potrzebować mniej czasu na wykonanie czynności związanych z układem i renderowaniem po zaktualizowaniu DOM. Nawet jeśli nie możesz znacząco zmniejszyć rozmiaru DOM, możesz zastosować pewne techniki, aby odizolować renderowanie do poddrzewa DOM, takie jak ograniczenie CSS i właściwość CSS content-visibility.

W każdym razie tworzenie środowiska, w którym renderowanie jest zminimalizowane, a także ograniczanie ilości renderowania wykonywanego przez stronę w odpowiedzi na interakcje użytkowników, sprawi, że Twoja witryna będzie się wydawać bardziej responsywna. Oznacza to, że Twoja witryna będzie mieć niższy INP, co przekłada się na lepsze wrażenia użytkowników.