Szybsze wczytywanie stron dzięki funkcji wczesnych podpowiedzi z serwera

Dowiedz się, jak serwer może wysyłać do przeglądarki wskazówki dotyczące kluczowych zasobów podrzędnych.

Co to są wczesne wskazówki?

Z czasem witryny stały się bardziej złożone. Dlatego nie jest niczym niezwykłym, że serwer musi wykonać niebanalną pracę (np. uzyskać dostęp do baz danych lub CDN-ów, które uzyskują dostęp do serwera źródłowego), aby wygenerować kod HTML strony, której dotyczy żądanie. Niestety ten „czas przetwarzania na serwerze” powoduje dodatkowe opóźnienie przed rozpoczęciem przez przeglądarkę renderowania strony. Połączenie jest nieaktywne przez cały czas, jaki serwer potrzebuje na przygotowanie odpowiedzi.

Obraz pokazujący przerwę w czasie przetwarzania na serwerze wynoszącą 200 ms między wczytaniem strony a wczytaniem innych zasobów.
Bez wczesnych wskazówek: na serwerze wszystko jest zablokowane, co określa, jaką odpowiedź ma zwrócić główny zasób.

Wczesne wskazówki to kod stanu HTTP (103 Early Hints) używany do wysyłania wstępnej odpowiedzi HTTP przed ostateczną odpowiedzią. Dzięki temu serwer może wysyłać do przeglądarki wskazówki dotyczące kluczowych zasobów podrzędnych (np. arkuszy stylów strony czy kluczowego kodu JavaScript) lub źródeł, których prawdopodobnie użyje strona, podczas gdy serwer generuje zasób główny. Podczas oczekiwania na główny zasób przeglądarka może używać tych wskazówek do rozgrzewania połączeń i wysyłania żądań dotyczących podzasobów. Innymi słowy, wczesne wskazówki pomagają przeglądarce korzystać z tego „czasu na przemyślenie” na serwerze, wykonując część pracy z wyprzedzeniem, co przyspiesza wczytywanie stron.

Obraz pokazujący, jak funkcja Wczesne wskazówki umożliwia stronie wysyłanie odpowiedzi częściowej.
Z wczesnymi podpowiedziami: serwer może wyświetlić częściową odpowiedź z podpowiedziami zasobów, gdy określa ostateczną odpowiedź

W niektórych przypadkach poprawa wydajności największego wyrenderowania treści może wynosić od kilkuset milisekund (jak w przypadku ShopifyCloudflare) do nawet sekundy (jak widać na tym porównaniu przed i po):

Porównanie dwóch witryn.
Porównanie w trybie „przed i po” wczesnych podpowiedzi na stronie testowej wykonane za pomocą narzędzia WebPageTest (Moto G4 – DSL)

Jak korzystać z wczesnych podpowiedzi

Pierwszym krokiem do korzystania z wcześniejszych wskazówek jest określenie najważniejszych stron docelowych, czyli stron, od których użytkownicy zwykle zaczynają przeglądanie Twojej witryny. Może to być strona główna lub strona popularnych produktów, jeśli masz wielu użytkowników z innych witryn. Te punkty wejścia są ważniejsze niż inne strony, ponieważ użyteczność wczesnych podpowiedzi maleje wraz z przemieszczaniem się użytkownika po witrynie (czyli przeglądarka ma większe szanse na to, że będzie mieć wszystkie potrzebne zasoby podrzędne podczas drugiego lub trzeciego przejścia). Warto też zadbać o dobre pierwsze wrażenie.

Po utworzeniu uporządkowanej listy stron docelowych należy określić, które źródła lub podzasoby nadają się do stosowania wskazówek preconnect lub preload. Zazwyczaj są to źródła i zasoby podrzędne, które mają największy wpływ na kluczowe dane o użytkownikach, takie jak Największe wyrenderowanie treści czy Pierwsze wyrenderowanie treści. Dokładniej rzecz biorąc, szukaj zasobów blokujących renderowanie, takich jak synchroniczny JavaScript, arkuszy stylów, a nawet czcionek internetowych. Analogicznie szukaj źródeł zawierających zasoby podrzędne, które w dużym stopniu wpływają na kluczowe dane o użytkownikach.

Pamiętaj też, że jeśli Twoje główne zasoby korzystają już z elementów preconnect lub preload, możesz uznać te źródła lub zasoby za kandydatów do wczesnych wskazówek. Więcej informacji o optymalizowaniu LCP znajdziesz w artykule Jak optymalizować LCP. Jednak naiwne kopiowanie dyrektyw preconnect i preload z HTML do wczesnych wskazówek może nie być optymalne.

Zazwyczaj używa się ich w HTML, aby preconnect lub preload zasobów, których skaner wstępnego ładowania nie wykryje w HTML, np. czcionek lub obrazów tła, które w przeciwnym razie zostaną wykryte zbyt późno. W przypadku wczesnych wskazówek nie masz kodu HTML, dlatego lepiej jest zamiast niego preconnect kierować do najważniejszych domen lub preload zasobów o krytycznym znaczeniu, które być może zostałyby wykryte na wczesnym etapie kodu HTML – na przykład przez wstępne wczytywanie main.css lub app.js.Poza tym nie wszystkie przeglądarki obsługują wczesne wskazówki preload – zapoznaj się z Pomocą dla przeglądarek.

Drugi krok polega na minimalizowaniu ryzyka użycia wczesnych wskazówek w przypadku zasobów lub źródeł, które mogą być nieaktualne lub nieużywane przez zasób główny. Na przykład zasoby, które są często aktualizowane i mają różne wersje (np. example.com/css/main.fa231e9c.css), mogą nie być najlepszym wyborem. Pamiętaj, że ten problem nie dotyczy wczesnych wskazówek. Dotyczy wszystkich funkcji preload lub preconnect, wszędzie tam, gdzie mogą się pojawić. Takie szczegóły najlepiej przetwarzać automatycznie lub za pomocą szablonów (np. ręczny proces spowoduje, że adresy URL haszy lub wersji w preload i rzeczywistym tagu HTML używającym zasobu mogą się nie zgadzać).

Oto przykładowy przepływ:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]

Serwer przewiduje, że będzie potrzebna main.abcd100.css, i sugeruje jej wstępne załadowanie za pomocą wczesnych podpowiedzi:

103 Early Hints
Link: </main.abcd100.css>; rel=preload; as=style
[...]

Chwilę później wyświetla się strona internetowa wraz z powiązaną usługą porównywania cen. Ten zasób CSS jest często aktualizowany, a zasób główny jest już o 5 wersji (abcd105) przed prognozowanym zasobem CSS (abcd100).

200 OK
[...]
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.abcd105.css">

Ogólnie staraj się wybierać zasoby i źródła, które są dość stabilne i w dużej mierze niezależne od wyniku głównego zasobu. W razie potrzeby możesz podzielić kluczowe zasoby na 2 części: stabilną część przeznaczoną do korzystania z wczesnych wskazówek i bardziej dynamiczną część, która będzie pobierana po otrzymaniu głównego zasobu przez przeglądarkę:

<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">

Na koniec na stronie serwera wyszukaj żądania głównych zasobów wysłane przez przeglądarki, które obsługują wczesne wskazówki, i natychmiast odpowiedz 103 wczesnymi wskazówkami. W odpowiedzi na żądanie 103 podaj odpowiednie wskazówki dotyczące wstępnego połączenia i wstępnego wczytania. Gdy główny zasób będzie gotowy, prześlij zwykłą odpowiedź (np. 200 OK w przypadku pomyślnego wykonania). Ze względu na zgodność wsteczną zalecamy również uwzględnianie w ostatecznej odpowiedzi nagłówków HTTP Link, a nawet uzupełnianie ich o krytyczne zasoby, które stały się widoczne podczas generowania głównego zasobu (np. dynamiczna część kluczowego zasobu, jeśli zastosowano sugestię „podzielenie na 2 części”). Oto jak to będzie wyglądać:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]
103 Early Hints
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script

Po chwili:

200 OK
Content-Length: 7531
Content-Type: text/html; charset=UTF-8
Content-encoding: br
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script
Link: </experimental.3eab3290.css>; rel=preload; as=style
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">
   <script src="/common.js"></script>
   <link rel="preconnect" href="https://fonts.googleapis.com">

Obsługa przeglądarek

Chociaż lista 103 wskazówek jest dostępna we wszystkich popularnych przeglądarkach, instrukcje dostępne we wczesnej ramach różnią się w zależności od przeglądarki:

Obsługa wstępnego połączenia:

Obsługa przeglądarek

  • Chrome: 103.
  • Edge: 103.
  • Firefox: 120.
  • Safari: 17.

Wsparcie dotyczące wstępnego wczytywania:

Obsługa przeglądarek

  • Chrome: 103.
  • Edge: 103.
  • Firefox: 123.
  • Safari: nieobsługiwane.

Narzędzia deweloperskie w Chrome obsługują też 103 wczesne wskazówki, a nagłówki Link można zobaczyć w zasobach dokumentu:

Panel sieciowy z nagłówkami wczesnych wskazówek
Nagłówki wczesnych wskazówek Link są wyświetlane w Narzędziach deweloperskich w Chrome.

Pamiętaj, że aby korzystać z zasobów wczesnych podpowiedzi, nie możesz zaznaczyć opcji Disable cache w narzędziach deweloperskich, ponieważ korzysta ona z pamięci podręcznej przeglądarki. W przypadku załadowanych wcześniej zasobów inicjator będzie widoczny jako early-hints, a rozmiar jako (Disk cache):

Panel sieciowy z informacjami o inicjatorach wczesnych podpowiedzi
Zasoby z wcześniejszym podpowiedzią mają inicjator early-hints i są ładowane z pamięci podręcznej na dysku.

Wymaga to też zaufanego certyfikatu do testowania HTTPS.

Firefox (od wersji 126) nie obsługuje w DevTools wyraźnie wczesnych podpowiedzi 103, ale zasoby wczytywane za pomocą wczesnych podpowiedzi nie zawierają informacji o nagłówku HTTP, co jest jednym z wskaźników, że zostały one wczytane za pomocą wczesnych podpowiedzi.

Obsługa serwerów

Oto krótkie podsumowanie poziomu obsługi funkcji Early Hints wśród popularnych oprogramowania open source do obsługi serwerów HTTP:

Włączanie wczesnych podpowiedzi w prostszy sposób

Jeśli korzystasz z jednego z tych CDN-ów lub platform, nie musisz ręcznie implementować wczesnych wskazówek. Aby dowiedzieć się, czy dostawca rozwiązania obsługuje wczesne wskazówki, zapoznaj się z dokumentacją online dostawcy Twojego rozwiązania. Możesz też zajrzeć na tę niepełną listę:

Jak uniknąć problemów w przypadku klientów, którzy nie obsługują wczesnych wskazówek

Informacyjne odpowiedzi HTTP w zakresie 100 są częścią standardu HTTP, ale niektóre starsze klienci lub boty mogą mieć z nimi problemy, ponieważ przed wprowadzeniem wersji 103 wczesnego podpowiadania były one rzadko używane do ogólnego przeglądania stron internetowych.

Wysyłanie podpowiedzi wczesnej 103 tylko w odpowiedzi na żądanie klienta, które zawiera nagłówek HTTP sec-fetch-mode: navigate, powinno zapewnić, że takie podpowiedzi są wysyłane tylko do nowszych klientów, którzy rozumieją, że muszą czekać na kolejną odpowiedź. Poza tym wczesne wskazówki są obsługiwane tylko w przypadku żądań nawigacji (patrz bieżące ograniczenia), dlatego ma to dodatkową korzyść w postaci uniknięcia niepotrzebnego wysyłania ich w przypadku innych żądań.

Ponadto wczesne wskazówki powinny być wysyłane tylko przez połączenia HTTP/2 lub HTTP/3, a większość przeglądarek akceptuje je tylko w ramach tych protokołów.

Wzór zaawansowany

Jeśli w pełni zastosowałeś wstępne wskazówki na najważniejszych stronach docelowych i szukasz nowych możliwości, możesz zainteresować się tym zaawansowanym wzorcem.

W przypadku użytkowników, którzy w ramach typowej ścieżki użytkownika przesyłają n-tą stronę, możesz dostosować odpowiedź z wczesnymi podpowiedziami do treści znajdujących się niżej i głębiej na stronie, czyli używać wczesnych podpowiedzi w przypadku zasobów o niższym priorytecie. Może się to wydawać nielogiczne, ponieważ zalecamy skupienie się na zasobach podrzędnych lub źródłach o wysokim priorytecie, które blokują renderowanie. Jednak gdy użytkownik już trochę pokieruje, przeglądarka prawdopodobnie będzie już miała wszystkie najważniejsze zasoby. Wtedy warto zająć się zasobami o mniejszym priorytecie. Może to na przykład oznaczać korzystanie ze wczesnych wskazówek w celu wczytywania zdjęć produktów lub używanie dodatkowych plików JS/CSS, które są potrzebne tylko w przypadku rzadziej spotykanych użytkowników.

Obecne ograniczenia

Oto ograniczenia wczesnej obsługi zapytań w Chrome:

  • Dostępne tylko w przypadku żądań nawigacji (czyli głównego zasobu dokumentu najwyższego poziomu).
  • Obsługiwane są tylko wartości preconnect i preload (czyli nieobsługiwana jest wartość prefetch).
  • Wczesne wskazówki, po których następuje przekierowanie między domenami w ostatecznej odpowiedzi, spowodują, że Chrome odrzuci zasoby i połączenia uzyskane za pomocą wczesnych wskazówek.
  • Zasoby wstępnie wczytane za pomocą wczesnych wskazówek są przechowywane w pamięci podręcznej HTTP i później pobierane z niej przez stronę. Dlatego tylko zasoby, które można przechowywać w pamięci podręcznej, można wstępnie wczytywać za pomocą wczesnych wskazówek. W przeciwnym razie zasób zostanie pobrany dwukrotnie (raz przez wczesne wskazówki, a potem przez dokument). W Chrome pamięć podręczna HTTP jest wyłączona w przypadku niesprawdzonych certyfikatów HTTPS (nawet jeśli wczytasz stronę).
  • Wstępne ładowanie obrazów elastycznych (za pomocą funkcji imagesrcset, imagesizes lub media) nie jest obsługiwane w przypadku nagłówków HTTP <link>, ponieważ widoczny obszar nie jest zdefiniowany do czasu utworzenia dokumentu. Oznacza to, że nie można używać wskazówek wczesnego wyświetlania do wstępnego wczytania obrazów elastycznych, ponieważ może to spowodować załadowanie nieprawidłowego obrazu. Zapoznaj się z tą dyskusją na temat propozycji, jak lepiej sobie z tym radzić.

Inne przeglądarki mają podobne ograniczenia, a jak wspomnieliśmy wcześniej, niektóre 103 wczesne wskazówki dotyczą tylko przeglądarki preconnect.

Co dalej?

W zależności od zainteresowania społeczności możemy rozszerzyć implementację wczesnych podpowiedzi o te funkcje:

  • Wczesne wskazówki dotyczące zasobów, których nie można przechowywać w pamięci podręcznej, z użyciem pamięci podręcznej zamiast pamięci podręcznej HTTP.
  • Wczesne wskazówki dotyczące żądań zasobów podrzędnych.
  • Wczesne wskazówki wysyłane w przypadku żądań głównych zasobów iframe.
  • Obsługa wstępnego pobierania w ramach wczesnych podpowiedzi.

Czekamy na Twoje opinie na temat tego, które aspekty powinny być priorytetowe i jak można jeszcze udoskonalić Wczesne wskazówki.

Relacja z H2/Push

Jeśli znasz wycofaną funkcję HTTP2/Push, możesz się zastanawiać, czym różnią się wczesne wskazówki. Wczesne wskazówki wymagają przesyłania w obie strony, aby przeglądarka mogła pobierać kluczowe zasoby podrzędne, natomiast przy HTTP2/Push serwer może zacząć przekazywać zasoby podrzędne wraz z odpowiedzią. Choć brzmiało to niesamowicie, doprowadziło do poważnego wady strukturalnej strony: podczas korzystania z protokołu HTTP2/Push bardzo trudno było uniknąć przekazywania zasobów podrzędnych, które przeglądarka już miała. Ten efekt „przesyłania” powodował mniej efektywne wykorzystanie przepustowości sieci, co znacznie ograniczało korzyści związane z wydajnością. Ogólnie dane Chrome pokazały, że protokół HTTP2/Push miały negatywny wpływ na wydajność w internecie.

W praktyce wczesna wskazówka działa lepiej, ponieważ łączy możliwość wysłania wstępnej odpowiedzi ze wskazówkami, które pozwalają przeglądarce samodzielnie pobierać lub łączyć się z tym, czego potrzebuje. Chociaż wczesne wskazówki nie obejmują wszystkich przypadków użycia, które teoretycznie obsługuje HTTP2/Push, uważamy, że wczesne wskazówki to bardziej praktyczne rozwiązanie do przyspieszania nawigacji.

Miniatura autorstwa Pierre Bamin.