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.

Kenji Baheux
Kenji Baheux

Czym są wczesne wskazówki?

Z czasem witryny internetowe stały się bardziej zaawansowane. Nie jest więc niczym niezwykłym, że serwer musi wykonać nieprostą pracę (na przykład uzyskać dostęp do baz danych lub sieci CDN uzyskujących dostęp do serwera pierwotnego), aby wygenerować kod HTML żądanej strony. Niestety, taki „czas zastanowienia serwera” powoduje wydłużenie czasu oczekiwania, zanim przeglądarka zacznie renderować stronę. W rzeczywistości połączenie jest w praktyce nieaktywne, dopóki serwer nie przygotuje odpowiedzi.

Obraz pokazujący 200-ms różnicy czasu między wczytaniem strony a wczytaniem innych zasobów.
Bez wczesnych wskazówek: na serwerze wszystko jest zablokowane i nie można zdecydować, jaka ma odpowiedź w przypadku zasobu głównego.

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. arkusza stylów strony, krytyczny kod JavaScript) lub źródeł, które prawdopodobnie będą używane przez stronę, gdy serwer jest zajęty generowaniem zasobu głównego. Przeglądarka może wykorzystać te wskazówki, aby rozgrzać połączenia i poprosić o zasoby podrzędne podczas oczekiwania na zasób główny. Innymi słowy, funkcja Early Hints pomaga przeglądarce wykorzystać „czas myślenia serwera”, wykonując pewne działania z wyprzedzeniem, by przyspieszyć ładowanie stron.

Obraz pokazujący, jak funkcja Early Hints umożliwia stronie wysyłanie częściowych odpowiedzi.
Dzięki funkcji wczesnych wskazówek: serwer może wysłać częściową odpowiedź ze wskazówkami dotyczącymi zasobów, gdy określa ostateczną odpowiedź.

W niektórych przypadkach poprawa wydajności największego wyrenderowania treści może wynosić nawet kilkaset milisekund (patrz Shopify i Cloudflare) lub nawet sekundę szybciej, jak widać na tym porównaniu:

Porównanie dwóch witryn.
Porównanie wczesnych wskazówek w witrynie testowej wykonanej za pomocą narzędzia WebPageTest (Moto G4 – DSL)

Wdrażanie wczesnych wskazówek

Zanim zagłębisz się w temat, pamiętaj, że funkcja Wczesne wskazówki nie jest przydatna, jeśli serwer może od razu wysłać 200 (lub inne odpowiedzi końcowe). W takich sytuacjach zamiast tego rozważ użycie zwykłego atrybutu link rel=preload lub link rel=preconnect w głównej odpowiedzi (nagłówek HTTP Link rel) lub w głównej odpowiedzi (elementy <link>). Poniżej znajdują się informacje o przypadkach, w których serwer potrzebuje trochę czasu na wygenerowanie głównej odpowiedzi.

Aby zacząć korzystać z wczesnych wskazówek, najpierw trzeba określić najpopularniejsze strony docelowe, czyli te, od których użytkownicy zwykle zaczynają odwiedzać Twoją witrynę. Może to być strona główna lub popularne strony z informacjami o produktach, jeśli wielu użytkowników odwiedza inne witryny. Punkty wejścia mają większe znaczenie niż inne strony, ponieważ przydatność wczesnych wskazówek maleje w miarę, jak użytkownik porusza się po witrynie (czyli przy drugiej lub trzeciej nawigacji z kolei w przeglądarce jest bardziej prawdopodobne, że będą w niej dostępne wszystkie zasoby podrzędne). Zawsze warto zrobić dobre pierwsze wrażenie.

Po utworzeniu tej listy stron docelowych z odpowiednim priorytetem następnym krokiem jest określenie, które źródła lub zasoby podrzędne byłyby dobrymi kandydatami do użycia wskazówek dotyczących wstępnego połączenia lub wstępnego wczytywania, w pierwszej kolejności. Zwykle są to źródła i zasoby podrzędne, które w największym stopniu wpływają na kluczowe dane o użytkownikach, takie jak Największe wyrenderowanie treści czy Pierwsze wyrenderowanie treści. Mówiąc bardziej szczegółowo, poszukaj zasobów podrzędnych blokujących renderowanie, takich jak synchroniczny JavaScript, arkusze stylów, a nawet czcionki internetowe. Podobnie poszukaj źródeł, które hostują zasoby podrzędne, które mają duży wpływ na kluczowe dane o użytkownikach. Uwaga: jeśli Twoje główne zasoby korzystają już z <link rel=preconnect> lub <link rel=preload>, możesz wziąć pod uwagę te źródła lub zasoby wśród kandydujących do programu wczesnych podpowiedzi. Więcej informacji znajdziesz w tym artykule.

Drugi krok polega na zminimalizowaniu ryzyka korzystania z 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 i dotyczy każdego linku rel=preload lub rel=preconnect, niezależnie od tego, gdzie się znajdują. Jest to rodzaj szczegółu, który najlepiej się sprawdza w przypadku automatyzacji lub tworzenia szablonów (np. w przypadku procesów ręcznych występuje większe prawdopodobieństwo, że w procesie ręcznym doprowadzi do niespójności haszu lub adresów URL wersji między elementem link rel=preload a rzeczywistym tagiem HTML korzystającym z zasobu).

Oto przykład:

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

Serwer przewiduje, że będzie potrzebny dyrektywa main.abcd100.css, i sugeruje wstępne wczytywanie za pomocą wczesnych wskazówek:

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

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

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

Zasadniczo staraj się znajdować zasoby i źródła, które są stosunkowo stabilne i w dużej mierze niezależne od wyniku wykorzystania głównego zasobu. W razie potrzeby możesz podzielić kluczowe zasoby na dwie części: część stabilną przeznaczoną do użytku z wczesnymi wskazówkami i część bardziej dynamiczną, która będzie pobierana po odebraniu 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 po stronie serwera wyszukaj główne żądania zasobów wysyłane przez przeglądarki, o których wiadomo, że obsługują funkcję wczesnych podpowiedzi, i odpowiedz natychmiast, używając 103 wczesnych wskazówek. W odpowiedzi 103 dołącz odpowiednie wskazówki dotyczące wstępnego łączenia i ładowania. Gdy zasób główny będzie gotowy, wyślij zwykłą odpowiedź (na przykład „200 OK”, jeśli operacja się udała). Aby zachować zgodność wsteczną, warto też w ostatniej odpowiedzi umieścić nagłówki HTTP Link, nawet jeśli dodasz do nich zasoby krytyczne, które stały się widoczne podczas generowania zasobu głównego (np. dynamiczną część zasobu klucza, jeśli skorzystasz z sugestii „podział na 2”). Mogłoby to wyglądać tak:

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

Kilka chwil później:

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ługiwane przeglądarki

Chociaż funkcja „103 wczesnych wskazówek” jest obsługiwana przez wszystkie popularne przeglądarki, dyrektywy, które można wysłać we wczesnej wskazówce, różnią się w zależności od przeglądarki:

Pomoc przed połączeniem:

Obsługa przeglądarek

  • 103
  • 103
  • 120
  • 17

Obsługa wstępnego wczytywania:

Obsługa przeglądarek

  • 103
  • 103
  • x

Obsługa serwerów

Oto krótkie podsumowanie poziomu obsługi wczesnych wskazówek w popularnym oprogramowaniu serwerowym HTTP OSS:

Obsługa wczesnych wskazówek w prosty sposób

Jeśli korzystasz z jednej z podanych niżej sieci CDN lub platform, nie musisz ręcznie implementować wczesnych wskazówek. Sprawdź w dokumentacji online danego dostawcy, czy obsługuje on wcześniejsze wskazówki. Możesz też przejrzeć niepełną listę:

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

Informacyjne odpowiedzi HTTP z zakresu 100 są częścią standardu HTTP, ale niektóre starsze klienty lub boty mogą mieć z nimi problemy, ponieważ przed wprowadzeniem 103 wczesnych wskazówek były one rzadko używane do ogólnego przeglądania internetu.

Wysyłanie takich wskazówek tylko w odpowiedzi na żądania 103 klientom, którzy wysyłają nagłówek żądania HTTP sec-fetch-mode: navigate, powinno zapewnić, że takie wskazówki będą wysyłane tylko w przypadku nowszych klientów, które rozumieją, że czekają na kolejną odpowiedź. Poza tym wczesne wskazówki są obsługiwane tylko w przypadku żądań nawigacji (zobacz bieżące ograniczenia), więc dodatkową zaletą jest uniknięcie niepotrzebnego wysyłania ich przy innych żądaniach.

Dodatkowo zalecamy, aby wczesne wskazówki były wysyłane tylko przez połączenia HTTP/2 lub HTTP/3.

Wzór zaawansowany

Jeśli udało Ci się w pełni zastosować wczesne wskazówki na kluczowych stronach docelowych i szukasz kolejnych możliwości, może zainteresować Cię poniższy wzorzec zaawansowany.

W przypadku użytkowników, którzy w ramach typowego zachowania użytkownika realizują n żądanie strony, możesz odpowiednio dostosować odpowiedź z wcześniejszymi wskazówkami do treści znajdujących się niżej i na dalszych etapach strony, np. przez użycie wczesnych wskazówek w przypadku zasobów o niższym priorytecie. Może to wydawać się sprzeczne z intuicją, ponieważ zalecamy skupienie się na zasobach podrzędnych lub źródłach blokujących renderowanie o wysokim priorytecie. Jeśli jednak użytkownik korzysta już z nawigacji przez dłuższy czas, jest bardzo prawdopodobne, że w jego przeglądarce są już dostępne wszystkie niezbędne zasoby. Z tego powodu być może warto przekierować uwagę na zasoby o niższym priorytecie. Może to np. oznaczać użycie wczesnych wskazówek do wczytywania zdjęć produktów albo dodatkowe pliki JS/CSS, które są potrzebne tylko w przypadku mniej typowych interakcji użytkowników.

Bieżące ograniczenia

Oto ograniczenia wczesnych wskazówek w Chrome:

  • Dostępne tylko w przypadku żądań nawigacyjnych (czyli głównego zasobu dokumentu najwyższego poziomu).
  • Obsługiwane są tylko właściwości preconnect i preload (czyli prefetch nie jest obsługiwane).
  • Wczesna wskazówka, a następnie w ostatniej odpowiedzi przekierowanie między domenami spowoduje, że Chrome zrzuci zasoby i połączenia uzyskane w ramach wczesnych podpowiedzi.

Inne przeglądarki mają podobne ograniczenia i jeszcze bardziej ograniczają 103 wczesne podpowiedzi tylko do przeglądarki preconnect.

Co dalej?

W zależności od zainteresowania społeczności możemy rozszerzyć wdrożenie wczesnych wskazówek o następujące funkcje:

  • Wysłano wczesne wskazówki dotyczące żądań zasobów podrzędnych.
  • Wczesne wskazówki zostały wysłane do żądań głównego zasobu elementu iframe.
  • Obsługa pobierania z wyprzedzeniem we wczesnych podpowiedziach.

Chętnie opowiedz nam, które aspekty należy traktować priorytetowo i jak ulepszyć te funkcje.

Związek z H2/Push

Jeśli znasz wycofaną funkcję HTTP2/Push, możesz zastanawiać się, czym różni się funkcja Wczesne wskazówki. Wczesne wskazówki wymagają, aby przeglądarka mogła rozpocząć pobieranie newralgicznych zasobów podrzędnych, natomiast przy użyciu protokołu HTTP2/Push serwer może rozpocząć przekazywanie zasobów podrzędnych razem z odpowiedzią. Brzmi to świetnie, ale miało to kluczową wadę strukturalną: w przypadku protokołu HTTP2/Push bardzo trudno było uniknąć przekazania zasobów podrzędnych, które już posiadała przeglądarka. Ten efekt „nadmiernego przekazywania” spowodował mniej efektywne wykorzystanie przepustowości sieci, co znacznie obniżyło korzyści związane z wydajnością. Ogólnie dane Chrome wykazały, że HTTP2/Push ma negatywny wpływ na wydajność w internecie.

Z kolei funkcja Wczesne wskazówki sprawdza się lepiej w praktyce, ponieważ łączy możliwość wysyłania wstępnej odpowiedzi ze wskazówkami, które pozostawiają przeglądarce kontrolę nad pobieraniem lub nawiązywaniem połączenia. Wczesne wskazówki nie obejmują wszystkich przypadków użycia, do których teoretycznie można odnieść się przez protokół HTTP2/Push, ale uważamy, że ta funkcja jest bardziej praktycznym rozwiązaniem w przypadku przyspieszenia nawigacji.

Miniatura: Pierre Bamin.