Zmniejsz zakres i złożoność obliczeń dotyczących stylu

JavaScript jest często reprezentatywną dla zmian wizualnych. Czasami zmiany są wprowadzane bezpośrednio przez manipulacje stylem, a czasem za pomocą obliczeń, które skutkują zmianami wizualnymi, takimi jak wyszukiwanie lub sortowanie danych. Niewłaściwie działający kod JavaScript lub jego długi czas działania mogą być częstą przyczyną problemów z wydajnością. Postaraj się więc zminimalizować jego wpływ.

Obliczanie stylu

Zmiana DOM przez dodawanie i usuwanie elementów, zmianę atrybutów, klas lub odtwarzania animacji sprawia, że przeglądarka ponownie oblicza style elementów, a w wielu przypadkach układ części lub całości strony. Jest to tzw. obliczanie stylu obliczonego.

Aby określić, które klasy, pseudoselektory i identyfikatory mają zastosowanie do danego elementu, przeglądarka zaczyna obliczać style, tworząc zestaw pasujących selektorów. Następnie przetwarza reguły stylu z pasujących selektorów i określa, jakie style końcowe są w danym elemencie.

Czas ponownego obliczania stylu i opóźnienie interakcji

Interakcja z kolejnym wyrenderowaniem (INP) to skoncentrowane na użytkownikach dane o wydajności środowiska wykonawczego, które oceniają ogólną responsywność strony w odniesieniu do danych wejściowych użytkownika. Mierzy czas oczekiwania na interakcję od momentu interakcji użytkownika ze stroną do momentu, gdy przeglądarka wyświetli następną ramkę zawierającą odpowiednie aktualizacje wizualne interfejsu.

Ważnym składnikiem interakcji jest czas potrzebny na wyrenderowanie następnej klatki. Renderowanie w celu zaprezentowania następnej klatki składa się z wielu części, w tym z obliczenia stylów strony bezpośrednio przed układem, malowaniem i komponowaniem. Na tej stronie skupiamy się na kosztach obliczania stylu, ale ograniczenie jakiegokolwiek etapu renderowania związanego z interakcją zmniejsza też całkowite czasy oczekiwania, także w przypadku obliczeń stylu.

Zmniejszenie złożoności selektorów

Uproszczenie nazw selektorów może przyspieszyć obliczanie stylu strony. Najprostsze selektory odwołują się do elementu w CSS tylko za pomocą nazwy klasy:

.title {
  /* styles */
}

Jednak wraz z rozwojem projektu prawdopodobnie będzie on wymagał bardziej złożonych arkuszy CSS, przez co mogą pojawić się selektory podobne do tych:

.box:nth-last-child(-n+1) .title {
  /* styles */
}

Aby określić, jak te style mają się do strony, przeglądarka musi zadać pytanie: „Czy jest to element z klasą title, którego element nadrzędny to element podrzędny minus-nth-plus-1 o klasie box?” Określenie tego może zająć dużo czasu, w zależności od używanego selektora oraz przeglądarki. Aby uprościć to zadanie, możesz zmienić selektor tak, aby był tylko nazwą klasy:

.final-box-title {
  /* styles */
}

Te nazwy klas zastępczych mogą wydawać się dziwne, ale znacznie upraszczają pracę przeglądarki. Aby na przykład w poprzedniej wersji przeglądarka mogła wiedzieć, że dany element jest ostatnim, musi najpierw wiedzieć wszystko o wszystkich pozostałych elementach, aby ustalić, czy po nim mogą występować nth-last-child elementy, które pojawiają się po nim. Może to być znacznie bardziej kosztowne pod względem obliczeniowym niż dopasowywanie selektora do elementu tylko dlatego, że jego klasa pasuje.

Zmniejsz liczbę elementów, do których nadaje się styl

Kolejnym istotnym aspektem, często ważniejszym niż złożoność selektora, jest nakład pracy potrzebny do wykonania zmiany elementu.

Ogólnie rzecz biorąc, najgorszym kosztem obliczenia stylu obliczonych elementów jest liczba elementów pomnożona przez liczbę selektora, ponieważ przeglądarka musi co najmniej raz sprawdzić każdy element pod kątem każdego stylu, aby sprawdzić, czy jest zgodny.

W obliczeniach stylu nie można unieważniać całej strony, a jednocześnie kierować reklamy na kilka elementów. W nowoczesnych przeglądarkach problem ten w mniejszym stopniu sprawia, że nie musi ona sprawdzać wszystkich elementów, na które wpływa zmiana. Z kolei starsze przeglądarki nie zawsze są zoptymalizowane pod kątem takich zadań. Gdy tylko jest to możliwe, zmniejsz liczbę nieprawidłowych elementów.

Mierz koszt ponownego obliczania stylu

Jednym ze sposobów sprawdzenia kosztu ponownego obliczenia stylu jest użycie panelu wydajności w Narzędziach deweloperskich w Chrome. Aby rozpocząć, wykonaj te czynności:

  1. Otwórz Narzędzia deweloperskie.
  2. Otwórz kartę Skuteczność.
  3. Kliknij Nagraj.
  4. Wejdź w interakcję ze stroną.

Po zatrzymaniu nagrywania zobaczysz obraz podobny do tego:

Narzędzia deweloperskie z obliczeniami stylu.
Raport Narzędzi deweloperskich z obliczeniami stylu.

Pasek u góry to miniaturowy wykres płomieniowy, który pokazuje też liczbę klatek na sekundę. Im bliżej dolnej krawędzi paska, tym szybciej klatki są malowane przez przeglądarkę. Jeśli na górze wykresu płomieniowego wyrównują się czerwone paski, oznacza to, że masz zadanie, które powoduje długotrwałe klatki.

Powiększenie obszaru problemu w Narzędziach deweloperskich w Chrome w podsumowaniu aktywności w wypełnionym panelu wydajności w Narzędziach deweloperskich w Chrome.
Długotrwałe klatki w podsumowaniu działań Narzędzi deweloperskich.

Warto przyjrzeć się długo trwającym klatkam podczas interakcji, np. podczas przewijania. Jeśli zobaczysz duży fioletowy blok, powiększ aktywność i wybierz dowolną pracę z etykietą Oblicz ponownie styl, aby uzyskać więcej informacji o potencjalnie kosztownych obliczeniach związanych ze stylem.

Uzyskiwanie szczegółów długo trwających obliczeń stylu, w tym istotnych informacji, takich jak liczba elementów, na które wpływa ponowne obliczanie stylu.
Długotrwałe przeliczanie stylu w podsumowaniu Narzędzi dla programistów trwa nieco ponad 25 ms.

Kliknięcie zdarzenia spowoduje wyświetlenie jego stosu wywołań. Jeśli renderowanie zostało spowodowane przez interakcję użytkownika, wywołuje kod JavaScript, który spowodował zmianę stylu. Pokazuje też liczbę elementów, których dotyczy zmiana (w tym przypadku ponad 900 elementów), oraz czas potrzebny na obliczenia stylu. Możesz skorzystać z tych informacji, aby znaleźć rozwiązanie w kodzie.

Użyj bloku, elementu, modyfikatora

Podejścia do kodowania takie jak BEM (Block, Element, Modifier) są wypiekane z wykorzystaniem selektora dopasowywania do korzyści w zakresie wydajności. BEM zaleca, aby wszystko miało jedną klasę, a jeśli potrzebujesz hierarchii, hierarchia ta jest również wbudowana w nazwę klasy:

.list {
  /* Styles */
}

.list__list-item {
  /* Styles */
}

Jeśli potrzebujesz modyfikatora, tak jak w przykładzie z ostatnim elementem podrzędnym, możesz go dodać w ten sposób:

.list__list-item--last-child {
  /* Styles */
}

BEM to dobry punkt wyjścia do porządkowania kodu CSS zarówno pod kątem struktury, jak i z uwagi na propagowane przez nią uproszczenia wyszukiwania stylów.

Jeśli nie podoba Ci się BEM, istnieją inne sposoby podejścia do CSS, ale najpierw oceń ich skuteczność i ergonomię.

Zasoby

Baner powitalny z serialu Unsplash, autor: Markus Spiske.