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?

Strony internetowe stają się z czasem coraz bardziej zaawansowane. 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 czas reakcji serwera wynoszący 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 kluczowych plików 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 wczesne wskazówki umożliwiają 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 2 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 wcześniejszych 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 wskazówek 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 drugiej lub trzeciej nawigacji). 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 podresursy, które w największym stopniu wpływają na kluczowe dane dotyczące użytkowników, takie jak największe wyrenderowanie treści lub pierwsze wyrenderowanie treści. Dokładniej rzecz biorąc, szukaj blokujących renderowanie zasobów pomocniczych, takich jak synchroniczny JavaScript, arkusze stylów czy nawet czcionki internetowe. Podobnie szukaj źródeł, które zawierają podzasoby, które w znaczącym 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 proste kopiowanie dyrektyw preconnectpreload 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 podpowiedzi nie masz kodu HTML, więc możesz zamiast tego preconnect do domen lub preload kluczowych zasobów, które mogą zostać wykryte we wczesnej części kodu HTML, np. do wstępnego wczytania main.css lub app.js. Ponadto nie wszystkie przeglądarki obsługują preload w przypadku wczesnych podpowiedzi (patrz Obsługa w przeglądarkach).

Drugim krokiem jest zminimalizowanie ryzyka użycia wczesnych wskazówek w przypadku zasobów lub źródeł, które mogą być nieaktualne lub nie są już używane przez zasób główny. Na przykład zasoby, które są często aktualizowane i utrzymywane w wersjach (np. example.com/css/main.fa231e9c.css), mogą nie być najlepszym wyborem. Pamiętaj, że ta kwestia nie dotyczy tylko wczesnych wskazówek, ale wszystkie elementy preload lub preconnect, niezależnie od tego, gdzie się znajdują. Takie szczegóły najlepiej przetwarzać automatycznie lub za pomocą szablonów (np. ręczny proces spowoduje większą szansę na niepasowanie adresów URL haszowanych lub wersji między preload a rzeczywistym tagiem HTML korzystającym z zasosobu).

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
[...]

Po kilku chwilach strona internetowa, w tym powiązany plik CSS, jest wyświetlana. Ten zasób CSS jest często aktualizowany, a zasób główny jest już o 5 wersji do przodu (abcd105) w stosunku do przewidywanego zasobu 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 użycia z wczesnymi wskazówkami 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 kilku chwilach:

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ż protokół 103 Early Hints jest obsługiwany we wszystkich głównych przeglądarkach, polecenia, które można wysłać w ramach wczesnego podpowiedzi, różnią się w zależności od przeglądarki:

Pomoc przed połączeniem:

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 Link Wczesna sugestia 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 również zaufanego certyfikatu na potrzeby 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 wczesnych podpowiedzi w popularnym oprogramowaniu open source serwera 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 lub przejrzyj tę niepełną listę:

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

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óry wysyła nagłówek żądania 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ź. Dodatkowo, ponieważ wczesne wskazówki są obsługiwane tylko w przypadku żądań nawigacyjnych (patrz obecne ograniczenia), nie trzeba ich niepotrzebnie wysyłać w przypadku innych żądań.

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

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 Early Hints do treści znajdujących się niżej na stronie lub głębiej w niej, czyli używać Early Hints w przypadku zasobów o niższym priorytecie. Może się to wydawać nielogiczne, ponieważ zalecamy skupienie się na blokujących renderowanie zasobach podrzędnych lub źródłach o wysokim priorytecie. 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ć użycie wczesnych podpowiedzi do wczytywania zdjęć produktów lub dodatkowego kodu JS/CSS, który jest potrzebny tylko do rzadszych interakcji użytkownika.

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 wczytywanie obrazów dostosowanych (za pomocą imagesrcset, imagesizes lub media) nie jest obsługiwane za pomocą nagłówków HTTP <link>, ponieważ widoczny obszar nie jest zdefiniowany, dopóki nie zostanie utworzony dokument. 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 dotyczących tego, jak lepiej sobie z tym poradzić.

Inne przeglądarki mają podobne ograniczenia, a jak już wspomnieliśmy, niektóre z nich jeszcze bardziej ograniczają wyświetlanie wskazówek w 103 dopiero do 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, zamiast pamięci podręcznej HTTP.
  • Wczesne wskazówki wysyłane w przypadku żądań dotyczących 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ć Wskazówki wczesne.

Związek 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ą od przeglądarki dwukierunkowej komunikacji, aby mogła zacząć pobierać kluczowe podresury, ale w przypadku HTTP2/Push serwer może zacząć przesyłać podresury wraz z odpowiedzią. Chociaż brzmi to niesamowicie, miało to jedną poważną wadę strukturalną: w przypadku HTTP2/Push bardzo trudno było uniknąć przesyłania 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 z Chrome pokazały, że HTTP2/Push w ogóle nie wpływa na wydajność w internecie.

W praktyce wczesna wskazówka działa lepiej, ponieważ łączy możliwość wysył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.