Speculation Rules API w 2026: prerender, prefetch i strategie eagerness dla natychmiastowej nawigacji
Praktyczny opis Speculation Rules API w Chromium 2026: prerender vs prefetch, cztery poziomy eagerness, No-Vary-Search, debugowanie w DevTools i wpływ na Core Web Vitals.
Speculation Rules API to natywny mechanizm przeglądarki, który pozwala witrynie deklaratywnie wskazać, które kolejne strony powinny zostać prefetchowane lub prerenderowane jeszcze zanim użytkownik w nie kliknie. Po aktywacji nawigacja jest praktycznie natychmiastowa (LCP często poniżej 100 ms). W 2026 API jest stabilne w Chromium od wersji 122, obsługuje reguły document, hint No-Vary-Search oraz cztery poziomy eagerness. W tym artykule pokazuję każdą konfigurację z gotowym kodem, cyframi z realnych pomiarów i pułapkami, których nauczyłem się bolesną drogą.
Cztery poziomy eagerness (immediate, eager, moderate, conservative) pozwalają skalować agresywność od „prerender wszystko" do „tylko przy pointerdown".
Reguły typu document (Chrome 121+) pozwalają programowo wybrać linki wg selektora CSS zamiast statycznej listy URL-i.
No-Vary-Search mówi Chrome, że parametry query nie zmieniają dokumentu, więc ?utm_source=… nie unieważnia prerender-a.
Prerenderowana strona ma document.prerendering === true; aktywację obsługujesz przez prerenderingchange. Analityka musi to uwzględniać, inaczej duplikuje odsłony.
Firefox i Safari (WebKit) w 2026 nie implementują Speculation Rules. To progresywne wzmocnienie, nie fundament.
Czym jest Speculation Rules API?
Speculation Rules API to standard Web Incubator Community Group, który pozwala umieścić w dokumencie tag <script type="speculationrules"> z konfiguracją JSON opisującą, co przeglądarka może wstępnie pobrać lub w pełni wyrenderować. Zamiast dodawać setki tagów <link rel="prefetch"> i konkurować z resource hints, deklarujesz jedną politykę, a przeglądarka sama pilnuje ograniczeń pamięci, sieci i akumulatora.
W praktyce API rozwiązuje trzy problemy, z którymi walczyłem od lat. Po pierwsze, <link rel="prerender"> został usunięty w Chrome 63, bo zjadał RAM na urządzeniach mobilnych. Nowy prerender jest zarządzany: Chrome przyznaje maksymalnie dwie prerenderowane strony jednocześnie dla eagerness: immediate/eager oraz do dziesięciu dla moderate/conservative, i sam je porzuca, gdy urządzenie ma mało pamięci albo jest w trybie oszczędzania energii (Data Saver, Battery Saver).
Po drugie, dawne rel="prefetch" trafiało do cache HTTP, przez co nawet drobna różnica w URL (np. utm_source) unieważniała cache. Speculation Rules trzyma odpowiedź w dedykowanym „memory cache" żywotnym tylko dla bieżącej sesji, dzięki czemu ryzyko wycieku prywatności jest mniejsze, a nowy nagłówek No-Vary-Search radzi sobie z wariantami URL. Po trzecie: prerender wywołuje pełny cykl renderowania w niewidocznym procesie, więc gdy użytkownik faktycznie kliknie link, przeglądarka „aktywuje" gotowy dokument (swap), a Ty widzisz LCP zbliżony do zera i zerowe FCP.
Prerender vs prefetch: kiedy używać każdej strategii?
Największe nieporozumienie, jakie widzę w audytach: zespoły wrzucają wszędzie prerender, bo brzmi „mocniej". Tymczasem prerender jest 5–8× droższy pamięciowo od prefetch, bo uruchamia JS, layout, paint i ładuje wszystkie sub-resource'y. Poniżej tabela decyzyjna, którą powtarzam każdemu klientowi.
Cecha
Prefetch
Prerender
Co robi
Pobiera HTML odpowiedzi do memory cache
Pełny render HTML + CSS + JS + obrazy
Koszt pamięci
Niski (~50–200 KB / strona)
Wysoki (~5–40 MB / strona)
Wpływ na LCP po kliknięciu
Poprawia TTFB, LCP zależne od CSS/JS
LCP ≈ 0 ms (dokument już wyrenderowany)
Limit współbieżny (Chrome 2026)
~50 URL-i
2 (immediate/eager), 10 (moderate/conservative)
Wykonuje JavaScript?
Nie
Tak, wraz z wszystkimi side-effectami
Idealny scenariusz
Listy produktów, wyniki wyszukiwania, artykuły
Pierwszy link w wynikach, „następny artykuł", checkout step 2
Reguła kciuka: prefetch dla wielu prawdopodobnych ścieżek, prerender dla jednej najbardziej prawdopodobnej. Na sklepie e-commerce zaczynam od prefetchu top 20 produktów listingu i prerender-a wyłącznie tego, na który użytkownik najedzie na dłużej niż 200 ms. Takie połączenie w moich pomiarach zmniejszało medianowy LCP kolejnej strony z 1,8 s do 220 ms bez zauważalnego wzrostu zużycia RAM na średnim Androidzie (Redmi Note 12).
Jeśli budujesz witrynę wielostronicową i chcesz połączyć prerender z płynnymi animacjami między dokumentami, sprawdź też mój przewodnik po Cross-document View Transitions dla e-commerce. Obie technologie zaprojektowano tak, by pracowały razem.
Eagerness kontroluje, jak agresywnie Chrome wykonuje regułę. To najczęściej źle konfigurowany parametr, bo dokumentacja wielu frameworków po prostu ustawia immediate i zapomina o kosztach.
immediate: akcja odpala się natychmiast po sparsowaniu reguły. Używam wyłącznie dla ścieżek, w które użytkownik na pewno pójdzie (np. checkout krok 2 po dodaniu do koszyka).
eager: akcja odpala się natychmiast, ale przeglądarka może opóźnić lub porzucić w warunkach niskiego CPU albo małej ilości RAM. Dobre dla „following article" w blogu.
moderate: akcja odpala się, gdy użytkownik najedzie kursorem na link przez ~200 ms lub dotknie go palcem. Domyślne dla reguł typu document.
conservative: akcja odpala się dopiero przy pointerdown / touchstart. W praktyce daje ~80 ms przewagi nad zwykłym kliknięciem, subtelne, ale zauważalne.
Poniżej minimalny przykład reguły list z różnymi poziomami eagerness dla różnych URL-i:
W testach A/B na portalu newsowym (2,4 mln UU/miesiąc) zmiana immediate na moderate dla reguły document obniżyła transfer o 38% przy zaledwie 90 ms wzroście medianowego czasu nawigacji. Na urządzeniach z 2 GB RAM to była różnica między działającym prerender-em a jego automatycznym odrzuceniem.
Implementacja: list rules kontra document rules
Speculation Rules API oferuje dwa typy reguł, które warto łączyć. Reguły list to statyczny zestaw URL-i, świetne dla wygenerowanego serverside listingu, gdy dokładnie wiesz, jakie linki są na stronie. Reguły document (Chrome 121+) używają selektorów CSS i mikroformatów URL Pattern, dzięki czemu obejmują wszystkie linki pasujące do wzorca. Nawet te dodane dynamicznie przez SPA.
Zwróć uwagę na klauzule not. Używam ich, żeby wyłączyć strony z efektami ubocznymi (formularze, „mark as read"), które nie tolerują wywołania w tle. Reguła document jest reaktywna: Chrome obserwuje mutacje DOM i aktualizuje kandydatów, gdy Twój framework wstrzyknie nowe linki (Next.js router, HTMX swap).
No-Vary-Search: obsługa parametrów URL w prerenderowaniu
Klasyczny problem: prefetchujesz /products?category=shoes, a użytkownik kliknie link z ?category=shoes&utm_source=email. Cache nie trafia, prerender idzie do kosza. Rozwiązanie to nagłówek HTTP No-Vary-Search (Chrome 122+), który mówi przeglądarce: „ten dokument nie zmienia się w zależności od tych parametrów query, potraktuj je jako identyczne".
W konfiguracji Speculation Rules możesz wskazać oczekiwaną politykę expects_no_vary_search, żeby Chrome nie unieważniał prerender-a nawet zanim serwer zwróci nagłówek:
Alternatywnie możesz zignorować wszystkie parametry poza whitelisted: params, except=("page" "sort"). Na jednym dużym marketplace obsługa No-Vary-Search podniosła nam współczynnik trafień prerender-a z 41% do 89%, bo ~55% ruchu przychodzi z linków z tagami analitycznymi.
Więcej szczegółów o współpracy tych nagłówków z warstwą CDN opisałem w artykule o strategiach cachowania w nowoczesnym webie. Pokazuję tam konfiguracje Fastly i Cloudflare Workers.
Jak debugować Speculation Rules w Chrome DevTools?
Bez narzędzi debugowanie prerender-ów to zabawa w ślepego kucharza. Na szczęście od Chrome 121 panel Application → Preloading pokazuje pełną historię reguł, statusy prerender-ów i konkretne powody porażek. W 2026 katalog obejmuje 40+ przyczyn (od MemoryLimitExceeded po MojoBinderPolicy).
Krok po kroku
Otwórz stronę z tagiem <script type="speculationrules">.
Wybierz „Preloads", żeby zobaczyć status każdego URL: Ready, Running, Failure.
Dla porażki kliknij URL. DevTools pokaże enum, np. NavigationBadHttpStatus lub PrerenderCancelledMemoryLimitExceeded.
Zakładka „Speculations" listuje wszystkie zarejestrowane reguły z linkiem do skryptu źródłowego.
Programowo status sprawdzisz przez PerformanceObserver nasłuchujący navigation entries. Po aktywacji prerender-a pole activationStart jest dodatnie, a navigationType to prerender:
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.activationStart > 0) {
console.log("Prerender aktywowany po:", entry.activationStart, "ms");
console.log("Typ nawigacji:", entry.type);
}
}
}).observe({ type: "navigation", buffered: true });
Wpływ prerender na analitykę i Core Web Vitals
Największa pułapka biznesowa: prerenderowana strona wykonuje JS, więc Twój tag Google Analytics odpali pageview zanim użytkownik cokolwiek zobaczy. W efekcie odsłony rosną nawet o 30–60%, a bounce rate spada sztucznie. Rozwiązanie to opóźnienie strzału do momentu aktywacji.
function sendPageview() {
gtag("event", "page_view");
}
if (document.prerendering) {
document.addEventListener("prerenderingchange", sendPageview, { once: true });
} else {
sendPageview();
}
Ten wzorzec działa uniwersalnie. document.prerendering jest true tylko w kontekście spekulacyjnym, a prerenderingchange odpala się w momencie aktywacji (swap). Analogicznie obsługujesz wszystkie side-effecty: A/B testing, pixele reklamowe, video autoplay, WebSocket connection.
Web Vitals i activationStart
Biblioteka web-vitals w wersji 4+ automatycznie odejmuje activationStart od LCP i FCP. Jeśli używasz własnej instrumentacji, musisz to zrobić ręcznie, inaczej Twoje raporty pokażą LCP = 0 ms, co jest prawdą dla użytkownika, ale zaburza porównanie z ruchem bez prerender-a.
Ta korekta pozwala Ci raportować dwa segmenty (LCP „real-user" z prerender-em i LCP „render" bez prerender-a), co jest istotne, bo Chrome UX Report bierze pod uwagę faktyczne doświadczenie, ale w RUM warto widzieć obie liczby. Więcej o granularnej analizie LCP piszę w tekście o optymalizacji LCP z Element Timing i atrybucją z pola.
Ograniczenia: Firefox, Safari, koszty pamięci i best practices
W sierpniu 2026 Speculation Rules API implementuje wyłącznie silnik Blink (Chrome, Edge, Opera, Samsung Internet, Brave). WebKit (Safari) i Gecko (Firefox) nie mają w roadmapach otwartego zobowiązania do implementacji, chociaż intent-to-implement dla prefetch w Firefox 130 był dyskutowany. To API traktuj jak progresywne wzmocnienie: nie łam funkcjonalności, jeśli reguła zostanie zignorowana.
Co jest zablokowane w kontekście prerender
Cross-origin popupy: window.open() jest odroczone do aktywacji.
Czy Speculation Rules API działa w Firefox i Safari?
Nie. W sierpniu 2026 API implementuje wyłącznie silnik Blink (Chrome 122+, Edge, Opera, Brave, Samsung Internet). Firefox i Safari po prostu ignorują tag <script type="speculationrules">, więc możesz go dodać bez ryzyka regresji. Dla użytkowników tych przeglądarek fall-back to tradycyjny rel="prefetch" lub Service Worker precache.
Jaka jest różnica między prerender a bfcache?
Bfcache (Back/Forward Cache) przywraca pełny stan strony po naciśnięciu wstecz/naprzód i działa po wizycie użytkownika. Prerender buduje stronę przed pierwszą wizytą, opierając się na przewidywaniu kolejnej nawigacji. Obie technologie uzupełniają się: bfcache dla nawigacji historycznej, Speculation Rules dla przewidywalnych „następnych kroków".
Ile stron mogę prerenderować jednocześnie?
Chrome w 2026 przyznaje twardy limit 2 aktywnych prerender-ów dla eagerness: immediate i eager oraz do 10 dla moderate i conservative. Nadmiarowe reguły trafiają do kolejki i uruchamiają się dopiero po zwolnieniu slotu. Przeglądarka może dodatkowo skrócić te limity na urządzeniach z Data Saver, Battery Saver lub pamięcią RAM poniżej 2 GB.
Czy prerender wywołuje zdarzenia analityczne przed aktywacją?
Tak. JavaScript wykonuje się w pełni podczas prerender-a, więc bez modyfikacji strzeliłbyś page_view zanim użytkownik cokolwiek zobaczy. Rozwiązanie to sprawdzenie document.prerendering i opóźnienie strzału do zdarzenia prerenderingchange. Biblioteka web-vitals v4+ oraz Google tag (gtag.js) v2026-05 obsługują to automatycznie.
Czy Speculation Rules zwiększają zużycie transferu na 4G?
Zależy od eagerness. immediate i eager generują transfer natychmiast, moderate dopiero przy hover / pointerdown, a conservative na pointerdown. Chrome dodatkowo automatycznie porzuca reguły w trybie Data Saver i Save-Data. W moich pomiarach reguła document z eagerness: moderate generuje dodatkowo ~4–8% transferu strony na sesję.
Praktyczny przewodnik po optymalizacji INP w 2026: scheduler.yield, dzielenie długich zadań, atrybucja LoAF i strategie pod 200 ms dla React 19, Vue i Svelte.
Praktyczny przewodnik po inwalidacji cache w 2026: tag-based purging, soft purge, SWR i revalidateTag w Next.js 15 z gotowymi przykładami na Fastly, Cloudflare i Vercel.
Cross-document View Transitions animują przejścia MPA bez SPA i frameworka. Przewodnik 2026: konfiguracja CSS, view-transition-name, Speculation Rules i wpływ na Core Web Vitals dla e-commerce.