Optymalizacja wczytywania zasobów

W poprzednim module teoria stojąca za krytyczną ścieżką renderowania była oraz jak zasoby blokujące renderowanie i parser mogą opóźnić do początkowego renderowania strony. Skoro już znasz teorię stojącą za zamierzasz poznać techniki optymalizacji ścieżki renderowania.

Podczas wczytywania strony w kodzie HTML odwołuje się wiele zasobów, które zapewniają wygląd i układ strony za pomocą CSS, a także jej interaktywność za pomocą JavaScriptu. W tym module omówimy kilka ważnych koncepcji związanych omówiono ich wpływ na czas wczytywania strony.

Jak wspomnieliśmy w poprzednim module, CSS to zasób render-blocking, bo blokuje ona przeglądarce możliwość renderowania jakichkolwiek treści do momentu użycia funkcji Obiektowego modelu CSS (CSSOM). Przeglądarka blokuje renderowanie, by zapobiec wyświetleniu Flasha Treści niestylizowane (FOUC), co jest niepożądane z punktu widzenia użytkowników.

W poprzednim filmie widać krótkie pole, na którym widać stronę bez do dowolnego stylu. Następnie wszystkie style są stosowane, gdy kod CSS strony została załadowana z sieci, a wersja bez stylu strony będzie natychmiast zastąpione wersją ze stylem.

Ogólnie rzecz biorąc, FOUC to coś, czego zwykle się nie widzimy, ale sam koncepcja jest ważne, aby wiedzieć, dlaczego przeglądarka blokuje renderowanie do czasu pobrania i zastosowania na stronie kodu CSS. Blokowanie renderowania nie jest to niepożądane, ale warto ograniczyć do minimum zoptymalizowanie usługi porównywania cen.

Blokowanie parsera

Zasób blokujący parser zakłóca działanie parsera HTML, np. <script> element bez atrybutów async lub defer. Gdy parser napotka <script>, przeglądarka musi ocenić i wykonać skrypt przed przy analizie pozostałej części kodu HTML. Jest to zamierzone, ponieważ skrypty mogą modyfikować lub uzyskiwać dostęp do DOM w trakcie jego tworzenia.

<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>

Jeśli używasz zewnętrznych plików JavaScript (bez elementów async i defer), parser jest jest blokowane od czasu wykrycia pliku do czasu pobrania, przeanalizowania . W przypadku korzystania z wbudowanego JavaScriptu parser jest w podobny sposób blokowany do skrypt w tekście zostanie przeanalizowany i wykonany.

.

Skaner wstępnego wczytywania

Skaner wstępnego wczytywania to funkcja optymalizacji przeglądarki w postaci dodatkowego kodu HTML parser, który skanuje nieprzetworzoną odpowiedź HTML w celu znalezienia i spekulacyjnego pobrania danych. przed ich wykryciem przez podstawowy parser HTML. Dla: np. skaner wstępnego wczytywania pozwoliłby przeglądarce rozpocząć pobieranie zasób określony w elemencie <img>, nawet jeśli parser HTML jest zablokowany podczas pobierania i przetwarzania zasobów, np. CSS i JavaScript.

Aby wykorzystać skaner wstępnego wczytywania, należy dostarczyć kluczowe zasoby w znacznikach HTML wysyłanych przez serwer. Poniższe wzorce wczytywania zasobów są niewykrywalne przez skaner wstępnego wczytywania:

  • Obrazy wczytywane przez CSS za pomocą właściwości background-image. Te obrazy odwołania są w CSS i nie mogą zostać wykryte przez skaner wstępnego wczytywania.
  • Dynamicznie ładowane skrypty w postaci wstrzykiwanych znaczników elementu <script> w DOM za pomocą JavaScriptu lub modułów wczytywanych za pomocą dynamicznego import().
  • Kod HTML wyrenderowany po stronie klienta za pomocą JavaScriptu. Takie znaczniki znajdują się w ciągów znaków w zasobach JavaScript i jest niewykrywalna przez wstępne wczytywanie skaner.
  • Deklaracje CSS @import.

Te wzorce wczytywania zasobów są zasobami znalezionymi późno, nie korzystają ze skanera wstępnego wczytywania. Jeśli to możliwe, unikaj ich. Jeśli unikanie takich wzorców nie jest możliwe, ale możesz wykorzystać Wskazówka preload dotycząca uniknięcia opóźnień w wykrywaniu zasobów.

CSS

CSS określa prezentację i układ strony. Jak już wspomnieliśmy, CSS to zasób blokujący renderowanie, więc optymalizacja CSS może mieć na ogólny czas wczytywania strony.

Minifikacja

Zmniejszanie plików CSS zmniejsza rozmiar pliku zasobu CSS, dzięki czemu ich pobieranie. Robi się to głównie przez usunięcie treści z źródłowego pliku CSS, takiego jak spacje i inne niewidoczne znaki, oraz wynik do nowo zoptymalizowanego pliku:

/* Unminified CSS: */

/* Heading 1 */
h1 {
  font-size: 2em;
  color: #000000;
}

/* Heading 2 */
h2 {
  font-size: 1.5em;
  color: #000000;
}
/* Minified CSS: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}

W najbardziej podstawowej formie minimalizacja CSS jest skuteczną metodą optymalizacji, poprawić FCP witryny, a w niektórych przypadkach nawet LCP. Narzędzia takie jak twórcy pakietów mogą automatycznie przeprowadzić tę optymalizację na ścieżce produkcyjnej do tworzenia kampanii.

Usuń nieużywany kod CSS

Przed wyrenderowaniem treści przeglądarka musi pobrać i przeanalizować wszystkie arkuszami stylów. Czas potrzebny na ukończenie analizy obejmuje także style, które nie są używane na bieżącej stronie. Jeśli korzystasz z usługi tworzenia pakietów, która łączy wszystkie elementy CSS do jednego pliku, użytkownicy prawdopodobnie pobierają więcej CSS niż potrzebne do wyrenderowania bieżącej strony.

Aby odkryć nieużywany kod CSS na bieżącej stronie, użyj narzędzia Pokrycie w Chrome Narzędzia deweloperskie.

Zrzut ekranu przedstawiający narzędzie pokrycia dostępnego w Narzędziach deweloperskich w Chrome. W dolnym panelu zostanie wybrany plik CSS. Zawiera on znaczną ilość kodu CSS nieużywanego przez obecny układ strony.
Narzędzie Zasięg w Narzędziach deweloperskich w Chrome przydaje się do wykrywania CSS (oraz JavaScript) nieużywane przez bieżącą stronę. Można go używać do dzielenia plików CSS do wielu zasobów, które mogą być ładowane przez różne strony, przesyłanie znacznie większego pakietu usług porównywania cen, co może opóźnić renderowanie strony.

Usunięcie nieużywanego kodu CSS ma 2 efekty: oprócz ograniczenia liczby pobrań optymalizujesz konstrukcję drzewa renderowania, ponieważ przeglądarka musi przetwarzania mniejszej liczby reguł CSS.

Unikaj deklaracji CSS @import

Chociaż może się to wydawać wygodne, należy unikać deklaracji @import w kodzie CSS:

/* Don't do this: */
@import url('style.css');

Podobnie jak w przypadku elementu <link> w kodzie HTML, deklaracja @import w CSS pozwala zaimportować zewnętrzny zasób CSS z poziomu arkusza stylów. główną różnicą między tymi dwoma podejściami jest to, że element HTML <link> jest częścią odpowiedzi HTML i dlatego można ją wykryć znacznie szybciej niż CSS pobrany plik w ramach deklaracji @import.

Powodem jest to, że aby deklaracja @import została najpierw należy pobrać plik CSS, który go zawiera. Ten powstaje tak zwany łańcuch żądań, który – w przypadku CSS – opóźnienia. ile czasu zajmuje pierwsze wyrenderowanie strony. Kolejną wadą jest to, arkuszy stylów wczytanych z użyciem deklaracji @import nie może skanować z wyprzedzeniem i w rezultacie stają się późno wykrytymi zasobami blokującymi renderowanie.

<!-- Do this instead: -->
<link rel="stylesheet" href="style.css">

W większości przypadków możesz zastąpić zmienną @import za pomocą parametru <link rel="stylesheet">. Elementy <link> umożliwiają arkusz stylów pobierane jednocześnie i skracają ogólny czas wczytywania w porównaniu z @import deklaracje, które po kolei pobierają arkusze stylów.

Wbudowany krytyczny kod CSS

Czas potrzebny na pobranie plików CSS może zwiększyć FCP strony. Wbudowana style krytyczne w dokumencie <head> eliminują żądanie sieciowe dla zasobów CSS, a po prawidłowym wykonaniu mogą skrócić czas wczytywania początkowego, pamięć podręczna przeglądarki użytkownika nie jest przygotowana. Pozostały kod CSS może zostać wczytany asynchronicznie, czyli dołączanego na końcu elementu <body>.

<head>
  <title>Page Title</title>
  <!-- ... -->
  <style>h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}</style>
</head>
<body>
  <!-- Other page markup... -->
  <link rel="stylesheet" href="non-critical.css">
</body>

Z drugiej strony wbudowanie dużej ilości kodu CSS powoduje zwiększenie liczby bajtów danych początkowych. odpowiedź HTML. Ponieważ zasobów HTML często nie można przechowywać w pamięci podręcznej na bardzo długo – wszystko – oznacza to, że wbudowany kod CSS nie jest buforowany dla kolejnych stron, które mogą ten sam kod CSS w zewnętrznych arkuszach stylów. Testowanie i pomiar aby mieć pewność, że kompromisy są warte wkładu.

Wersje demonstracyjne CSS

JavaScript

JavaScript zapewnia większość interaktywności w internecie, ale wiąże się to z kosztami. Zbyt duża ilość kodu JavaScript może spowolnić reagowanie Twojej strony podczas przesyłania może powodować problemy z responsywnością i spowalniać interakcje. co może być frustrujące dla użytkowników.

Kod JavaScript blokujący renderowanie

Podczas wczytywania elementów <script> bez atrybutu defer lub async parametr przeglądarka blokuje analizowanie i renderowanie, dopóki skrypt nie zostanie pobrany, przeanalizowany . Podobnie wbudowane skrypty blokują parser do czasu przeanalizowania skryptu i wykonano.

async kontra defer

async i defer pozwalają na ładowanie zewnętrznych skryptów bez blokowania kodu HTML parser, a skrypty (w tym wbudowane skrypty) z type="module" są jest odroczone automatycznie. async i defer mają jednak pewne różnice, są bardzo ważne.

Omówienie różnych mechanizmów wczytywania skryptów ze szczegółowym opisem ról parsera, pobierania i wykonania na podstawie różnych użytych atrybutów, takich jak asynchroniczny, opóźnienie, type=&#39;moduł&#39; i kombinacji wszystkich 3 elementów.
Źródło: https://html.spec.whatwg.org/multipage/scripting.html
.

Skrypty wczytane za pomocą funkcji async są analizowane i uruchamiane natychmiast po pobraniu, a skrypty wczytane przy użyciu metody defer są wykonywane, gdy włączona jest analiza dokumentu HTML zakończone – następuje to w tym samym czasie co zdarzenie DOMContentLoaded przeglądarki. Dodatkowo skrypty async mogą być wykonywane w innej kolejności, a defer są wykonywane w takiej kolejności, w jakiej występują w znacznikach.

Renderowanie po stronie klienta

Zasadniczo nie należy używać JavaScriptu do renderowania treści krytycznych ani element LCP strony. Jest to tzw. renderowanie po stronie klienta. To technika, jest często wykorzystywany w aplikacjach jednostronicowych (SPA).

Znaczniki renderowane przez JavaScript pomijają skaner wstępnego wczytywania, zawarte w znacznikach renderowanych przez klienta nie są dla nich wykrywalne. Ten może opóźnić pobieranie kluczowych zasobów, takich jak obraz LCP. Przeglądarka rozpoczyna pobieranie obrazu LCP dopiero po wykonaniu skryptu, elementu do DOM. Z kolei skrypt można wykonać dopiero wtedy, gdy zostały wykryte, pobrane i przeanalizowane. Jest to tzw. żądanie krytyczne łańcuchowe i należy go unikać.

Ponadto renderowanie znaczników za pomocą języka JavaScript daje większe prawdopodobieństwo wygenerowania długie zadania niż znaczniki pobierane z serwera w odpowiedzi na nawigację użytkownika. Intensywne wykorzystywanie renderowania HTML po stronie klienta może negatywnie wpłynąć czas oczekiwania na interakcję Dotyczy to szczególnie sytuacji, gdy DOM strony jest bardzo duży rozmiar, który aktywuje znaczącą pracę renderowania, gdy kod JavaScript modyfikuje tekst. czyli DOM.

Minifikacja

Podobnie jak w przypadku CSS, zmniejszanie kodu JavaScript zmniejsza rozmiar pliku zasobu skryptu. Może to przyspieszyć pobieranie, dzięki czemu przeglądarka będzie mogła przejść przetwarzania i kompilowania JavaScriptu.

Co więcej, minifikacja JavaScriptu idzie o krok dalej niż zmniejszanie. z innymi komponentami, takimi jak usługa porównywania cen. Zmniejszenie JavaScriptu nie tylko usuwa takich jak spacje, tabulatory i komentarze, ale symbole w źródle JavaScript jest skracany. Ten proces jest czasami nazywany uglyfikacją. Do zobaczysz różnicę. W tym celu użyj następującego kodu źródłowego JavaScript:

// Unuglified JavaScript source code:
export function injectScript () {
  const scriptElement = document.createElement('script');
  scriptElement.src = '/js/scripts.js';
  scriptElement.type = 'module';

  document.body.appendChild(scriptElement);
}

Jeśli poprzedni kod źródłowy JavaScript jest ugllifikowany, wynik może wyglądać tak podobny do tego fragmentu kodu:

// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}

W poprzednim fragmencie widać, że zmienna czytelna dla człowieka scriptElement w źródle został skrócony do t. Gdy zastosujesz na pozyskanych skryptów, oszczędności mogą być znaczne, bez wpływu funkcje produkcyjnego kodu JavaScript witryny.

Jeśli do przetwarzania kodu źródłowego witryny korzystasz z usług pakietu SDK, często odbywa się automatycznie w przypadku kompilacji produkcyjnych. bulatory – takie jak Terser, są na przykład bardzo elastyczne, co pozwala na dostosowywanie bardziej agresywne algorytm uglyfikowania w celu osiągnięcia maksymalnych oszczędności. Domyślne ustawienia każdego narzędzia do tworzenia rozszerzeń są zwykle wystarczające, aby generować ostrzeżenia. zachować równowagę między rozmiarem wyjściowym a zachowaniem możliwości.

Wersje demonstracyjne JavaScript

Sprawdź swoją wiedzę

Jaki jest najlepszy sposób na wczytanie wielu plików CSS w przeglądarce?

Wiele elementów <link>.
Deklaracja @import usługi porównywania cen.

Do czego służy skaner wstępnego ładowania przeglądarki?

Wykrywa elementy <link rel="preload"> w: zasób HTML.
Jest to dodatkowy parser HTML, który analizuje nieprzetworzone znaczniki w celu wykrycia przed parserem DOM.

Dlaczego przeglądarka domyślnie blokuje analizy HTML, gdy pobierania zasobów JavaScript?

Zapobieganie rozprzestrzenianiu się niesformatowanych treści.
Ponieważ skrypty mogą modyfikować DOM lub uzyskiwać do niego dostęp w inny sposób.
Ponieważ ocena JavaScriptu wymaga dużego obciążenia procesora i jest wstrzymana Analiza HTML zapewnia większą przepustowość procesora na potrzeby zakończenia wczytywania skryptów.

Następny krok: wsparcie przeglądarki za pomocą wskazówek dotyczących zasobów

Wiesz już, jak zasoby wczytywane w elemencie <head> mogą wpływ na początkowe wczytywanie strony i różne wskaźniki, czas przejść do następnego kroku. W ciągu następnych wskazówki dotyczące zasobów oraz sposoby ich wykorzystania przeglądarka, aby rozpocząć ładowanie zasobów i otwierać połączenia z innymi domenami szybciej niż przeglądarka.