Speculation Rules API în 2026: Ghid Practic pentru Navigare Instantanee cu Prerendering și bfcache

Ghid practic despre Speculation Rules API cu exemple de cod pas cu pas. Învățați cum să implementați prerendering, prefetching și bfcache pentru navigare web instantanee, cu strategii pentru e-commerce și optimizarea Core Web Vitals.

De Ce Contează (Cu Adevărat) Navigarea Instantanee

Să fim sinceri: în 2026, nimeni nu mai are răbdare să aștepte ca o pagină web să se încarce. Utilizatorii se așteaptă ca tranzițiile între pagini să fie aproape imperceptibile, iar Google folosește Core Web Vitals ca factori de clasificare în rezultatele căutării. Un LCP (Largest Contentful Paint) care depășește 3 secunde? Asta poate însemna o pierdere de trafic de până la 23% față de competitorii mai rapizi.

Aici intră în scenă Speculation Rules API.

Această interfață permite browser-ului să înceapă încărcarea și chiar randarea paginilor viitoare înainte ca utilizatorul să dea clic. Practic, browser-ul „ghicește" unde va naviga vizitatorul și pregătește totul în avans. Combinată cu bfcache (Back/Forward Cache) și strategii inteligente de prefetching, poate reduce dramatic timpii de încărcare.

În acest ghid, vom explora pas cu pas cum funcționează Speculation Rules API, cum o implementați corect, cum optimizați bfcache și cum măsurați impactul real asupra Core Web Vitals. Fie că administrați un blog, un magazin online sau o aplicație web complexă — aceste tehnici vă vor transforma experiența de navigare a utilizatorilor.

Ce Este Speculation Rules API, Mai Exact?

Speculation Rules API este o interfață web nativă disponibilă în browserele bazate pe Chromium (Chrome, Edge, Opera) care permite dezvoltatorilor să declare reguli pentru pre-încărcarea paginilor viitoare. Dacă ați folosit vreodată <link rel="prefetch"> sau <link rel="prerender"> (acum deprecated), gândiți-vă la Speculation Rules ca la versiunea lor mult mai inteligentă și mai controlabilă.

Prefetching vs. Prerendering: Care-i Diferența?

API-ul oferă două moduri principale de funcționare, și diferența dintre ele contează enorm:

  • Prefetch (Pre-încărcare): Browser-ul descarcă resursele cheie ale unei pagini — documentul HTML, CSS-ul critic, fonturile — dar nu o randează. Când utilizatorul navighează efectiv, pagina trebuie totuși randată, dar pornește de la resurse deja disponibile în cache.
  • Prerender (Pre-randare): Browser-ul descarcă și randează complet pagina într-un tab invizibil. Când utilizatorul dă clic, pagina apare instantaneu, fără nicio întârziere vizibilă. Aceasta e varianta „magică".

Diferența de performanță e semnificativă. Datele Chrome arată că prerendering-ul poate reduce LCP la percentila 95 cu aproximativ 500 ms, iar la percentila 75 cu circa 170 ms. Prefetch-ul aduce câștiguri mai modeste, dar încă relevante.

Cum Arată Regulile de Speculare

Regulile se declară ca JSON în interiorul unui tag <script type="speculationrules">. Iată forma cea mai simplă:

<script type="speculationrules">
{
  "prerender": [
    {
      "source": "list",
      "urls": ["/pagina-urmatoare", "/despre-noi"]
    }
  ]
}
</script>

O listă statică de URL-uri pe care browser-ul le va pre-randa. Simplu, nu? Dar API-ul oferă mult mai mult decât atât.

Reguli pe Bază de Document: Unde Devine Interesant

Sincer, listele statice de URL-uri sunt rareori practice pe un site real. Regulile pe bază de document permit browser-ului să identifice automat link-urile relevante de pe pagina curentă și să aplice specularea pe baza unor condiții.

Selectoare CSS pentru Identificarea Link-urilor

Puteți folosi selectoare CSS pentru a specifica exact care link-uri să fie pre-încărcate:

<script type="speculationrules">
{
  "prerender": [
    {
      "source": "document",
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": { "href_matches": "/admin/*" } },
          { "not": { "href_matches": "/logout" } },
          { "not": { "selector_matches": ".no-prerender" } }
        ]
      },
      "eagerness": "moderate"
    }
  ]
}
</script>

Ce face acest exemplu? Spune browser-ului: „Pre-randează orice link intern, cu excepția paginilor de administrare, a paginii de logout și a link-urilor marcate cu clasa .no-prerender". Frumusețea abordării e că funcționează automat pe toate paginile, fără liste manuale.

Pattern-uri URL cu href_matches

Proprietatea href_matches acceptă pattern-uri URL conform standardului URLPattern. Câteva exemple utile:

// Doar paginile de produs
{ "href_matches": "/produse/:id" }

// Doar paginile dintr-o categorie specifică
{ "href_matches": "/categorie/electronice/*" }

// Orice pagină de pe același domeniu
{ "href_matches": "/*" }

// Doar paginile de blog
{ "href_matches": "/blog/:slug" }

Niveluri de Eagerness: Cât de Agresiv Să Fie Specularea?

Setarea eagerness e probabil cea mai importantă decizie pe care o veți lua. Controlează echilibrul dintre performanță și consumul de resurse. API-ul oferă patru niveluri:

  • immediate: Specularea începe imediat ce regulile sunt detectate. Ideal pentru paginile pe care sunteți siguri că utilizatorul le va vizita — de exemplu, pasul următor dintr-un wizard multi-step.
  • eager: Similar cu immediate, dar pe mobil (de la ianuarie 2026) Chrome a modificat comportamentul: specularea se declanșează la 50ms după ce un link intră în viewport.
  • moderate: Specularea se activează când utilizatorul ține cursorul peste un link timp de 200ms. Aceasta e alegerea pe care o recomand pentru majoritatea site-urilor — suficient de rapidă, dar conservatoare cu resursele.
  • conservative: Specularea se activează doar la pointer down sau touch start — practic, când utilizatorul e pe cale să dea clic. Cel mai mic consum de resurse, valoarea implicită pentru document rules.

Ce Nivel Să Alegeți?

Din experiență, o abordare stratificată funcționează cel mai bine:

// Pentru navigarea principală (meniu, CTA-uri)
{
  "source": "document",
  "where": { "selector_matches": "nav a, .cta-primary" },
  "eagerness": "eager"
}

// Pentru link-urile din conținut
{
  "source": "document",
  "where": { "selector_matches": "article a" },
  "eagerness": "moderate"
}

// Pentru restul link-urilor interne
{
  "source": "document",
  "where": { "href_matches": "/*" },
  "eagerness": "conservative"
}

Puteți combina mai multe reguli în același script — browser-ul le aplică pe toate simultan.

Implementare Practică: Pas cu Pas

Hai să trecem de la teorie la practică. Vom construi implementarea progresiv, de la simplu la complex.

Pasul 1: Implementare Minimă

Cel mai simplu mod de a începe — adăugați un script de speculare în <head>:

<!DOCTYPE html>
<html lang="ro">
<head>
  <meta charset="UTF-8">
  <title>Exemplu Speculation Rules</title>

  <script type="speculationrules">
  {
    "prefetch": [
      {
        "source": "document",
        "where": { "href_matches": "/*" },
        "eagerness": "moderate"
      }
    ]
  }
  </script>
</head>
<body>
  <!-- Conținutul paginii -->
</body>
</html>

Începeți cu prefetch în loc de prerender pentru a valida că totul funcționează corect. Apoi treceți la prerendering pentru paginile cele mai importante.

Pasul 2: Trecerea la Prerendering

Odată ce prefetch-ul merge bine, puteți face upgrade la prerendering pentru paginile cu impact maxim:

<script type="speculationrules">
{
  "prerender": [
    {
      "source": "document",
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": { "href_matches": "/cos-cumparaturi" } },
          { "not": { "href_matches": "/checkout/*" } },
          { "not": { "href_matches": "/cont/*" } },
          { "not": { "selector_matches": "[data-no-prerender]" } }
        ]
      },
      "eagerness": "moderate"
    }
  ],
  "prefetch": [
    {
      "source": "document",
      "where": {
        "or": [
          { "href_matches": "/cos-cumparaturi" },
          { "href_matches": "/checkout/*" },
          { "href_matches": "/cont/*" }
        ]
      },
      "eagerness": "conservative"
    }
  ]
}
</script>

Observați strategia: paginile de conținut sunt pre-randate (deci instantanee), în timp ce paginile cu stare (coș, checkout, cont) sunt doar pre-încărcate, evitând problemele cu datele dinamice.

Pasul 3: Livrare prin Header HTTP

O alternativă elegantă e să livrați regulile prin header-ul HTTP Speculation-Rules:

# Configurare Nginx
location / {
    add_header Speculation-Rules "/speculation-rules.json";
}

# Sau în Apache (.htaccess)
Header set Speculation-Rules "/speculation-rules.json"

Iar fișierul /speculation-rules.json conține regulile JSON:

{
  "prerender": [
    {
      "source": "document",
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": { "href_matches": "/api/*" } }
        ]
      },
      "eagerness": "moderate"
    }
  ]
}

Avantajul? Regulile pot fi modificate la nivel de server fără a atinge template-urile HTML.

Detectarea Suportului și Fallback

Speculation Rules API funcționează în Chrome 121+, Edge 121+ și Opera 107+. Firefox și Safari nu o suportă încă (deși există semne promițătoare de adoptare cross-browser în 2026). E important să implementați detecția suportului:

if (HTMLScriptElement.supports &&
    HTMLScriptElement.supports("speculationrules")) {
  // Browser-ul suportă Speculation Rules API
  const specScript = document.createElement("script");
  specScript.type = "speculationrules";
  specScript.textContent = JSON.stringify({
    prerender: [{
      source: "document",
      where: { href_matches: "/*" },
      eagerness: "moderate"
    }]
  });
  document.head.appendChild(specScript);
} else {
  // Fallback: prefetch clasic pentru link-urile importante
  const importantLinks = document.querySelectorAll("nav a");
  importantLinks.forEach(link => {
    const prefetchLink = document.createElement("link");
    prefetchLink.rel = "prefetch";
    prefetchLink.href = link.href;
    document.head.appendChild(prefetchLink);
  });
}

Acest pattern de progressive enhancement asigură că utilizatorii tuturor browserelor beneficiază de o formă de pre-încărcare. Nimeni nu rămâne pe dinafară.

Optimizarea bfcache: Navigarea Înapoi Fără Așteptare

bfcache este o optimizare de browser complementară (și adesea subestimată) care face navigarea cu butoanele Înapoi/Înainte aproape instantanee. În loc să distrugă pagina când utilizatorul navighează, browser-ul o „îngheață" în memorie și o restaurează imediat la revenire.

De Ce Merită Atenție

Datele Chrome arată că 10% din navigările pe desktop și 20% pe mobil sunt navigări înapoi sau înainte. Asta e o proporție semnificativă din vizite pe care o puteți optimiza. Și partea bună? Aproximativ 98% din browserele moderne suportă bfcache.

Ce Blochează bfcache

Iată principalele „vinovate" care împiedică o pagină să fie stocată în bfcache:

  1. Header-ul Cache-Control: no-store: Spune explicit browser-ului să nu stocheze pagina. Dacă îl folosiți pe paginile de conținut, bfcache nu va funcționa.
  2. Event listener-ul unload: Considerat deprecated și un blocaj clasic pentru bfcache. Chrome plănuiește să îl deprecize complet.
  3. Conexiuni WebSocket sau WebRTC active: Conexiunile deschise pot împiedica stocarea.
  4. API-uri incompatibile: BroadcastChannel cu mesaje neachitate sau lock-uri Web Locks active pot bloca bfcache.

Cum Optimizați pentru bfcache

// ❌ NU folosiți evenimentul unload
window.addEventListener("unload", () => {
  // Această abordare blochează bfcache
  sendAnalytics();
});

// ✅ Folosiți pagehide în schimb
window.addEventListener("pagehide", (event) => {
  if (!event.persisted) {
    // Pagina este distrusă definitiv
    sendAnalytics();
  }
  // Dacă event.persisted === true, pagina intră în bfcache
});

// ✅ Detectați restaurarea din bfcache
window.addEventListener("pageshow", (event) => {
  if (event.persisted) {
    // Pagina a fost restaurată din bfcache
    refreshCartCount();
    checkSessionValidity();
  }
});

Închiderea Conexiunilor la Ieșire

// Închideți WebSocket-urile la pagehide
let ws = new WebSocket("wss://api.exemplu.ro/live");

window.addEventListener("pagehide", () => {
  ws.close();
});

// Reconectați la pageshow dacă e nevoie
window.addEventListener("pageshow", (event) => {
  if (event.persisted) {
    ws = new WebSocket("wss://api.exemplu.ro/live");
  }
});

Testarea bfcache în Chrome DevTools

Chrome DevTools are un instrument dedicat pentru testarea bfcache — și e foarte simplu de folosit:

  1. Deschideți DevTools (F12)
  2. Navigați la tab-ul Application
  3. În panoul din stânga, selectați Back/forward cache
  4. Apăsați butonul Test back/forward cache
  5. DevTools va naviga și reveni automat, raportând dacă bfcache a funcționat sau ce l-a blocat

Prerender Until Script: Noutatea din Chrome 144

Începând cu Chrome 144, o funcționalitate experimentală numită „Prerender Until Script" oferă un compromis interesant între prefetch și prerender complet. Ideea: browser-ul pre-încarcă documentul HTML și începe randarea, inclusiv descărcarea tuturor sub-resurselor, dar se oprește înainte de executarea script-urilor.

De ce e util? Pentru paginile care au efecte secundare în JavaScript (trimiterea de analytics, modificarea stării serverului) — randarea vizuală e pregătită, dar logica de business se execută doar când utilizatorul navighează efectiv. Un compromis elegant, sincer.

Combinarea cu Service Workers

Pentru o strategie de navigare cu adevărat robustă, puteți combina Speculation Rules API cu Service Workers:

// service-worker.js
const CACHE_NAME = "navigare-rapida-v1";
const PRECACHE_URLS = [
  "/css/critical.css",
  "/js/app.bundle.js",
  "/fonts/inter-var.woff2"
];

self.addEventListener("install", (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      return cache.addAll(PRECACHE_URLS);
    })
  );
});

// Strategie: Network First cu fallback pe cache
self.addEventListener("fetch", (event) => {
  if (event.request.mode === "navigate") {
    event.respondWith(
      fetch(event.request)
        .then((response) => {
          const clone = response.clone();
          caches.open(CACHE_NAME).then((cache) => {
            cache.put(event.request, clone);
          });
          return response;
        })
        .catch(() => {
          return caches.match(event.request);
        })
    );
  }
});

Ce obțineți din această combinație? Navigare instantanee prin Speculation Rules pentru link-urile anticipate, încărcare rapidă din cache pentru resurse statice prin Service Worker, plus fallback offline pentru paginile vizitate anterior. Practic, acoperiți toate scenariile.

Măsurarea Impactului: Metrici și Instrumente

Implementarea fără măsurare e ca și cum ai zbura pe orbită — arată impresionant, dar nu știi dacă mergi în direcția bună.

Monitorizarea cu Performance Observer

Iată cum măsurați impactul speculării asupra Core Web Vitals:

// Monitorizarea LCP
const lcpObserver = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];

  console.log("LCP:", lastEntry.startTime, "ms");
  console.log("Element:", lastEntry.element);

  // Verificați dacă pagina a fost pre-randată
  const navEntry = performance.getEntriesByType("navigation")[0];
  if (navEntry.activationStart > 0) {
    console.log("Pagina a fost pre-randată!");
    console.log("LCP ajustat:",
      lastEntry.startTime - navEntry.activationStart, "ms");
  }
});

lcpObserver.observe({ type: "largest-contentful-paint", buffered: true });

// Verificarea tipului de navigare
const navEntries = performance.getEntriesByType("navigation");
if (navEntries.length > 0) {
  const nav = navEntries[0];
  console.log("Tip navigare:", nav.type);
  // "navigate", "reload", "back_forward", "prerender"

  if (nav.type === "back_forward") {
    console.log("Navigare din bfcache (instantanee)");
  }
  if (nav.activationStart > 0) {
    console.log("Navigare prerandată (instantanee)");
  }
}

Debugging în Chrome DevTools

Chrome DevTools vine cu instrumente dedicate pentru depanarea Speculation Rules:

  1. Deschideți tab-ul Application în DevTools
  2. Navigați la secțiunea Speculative loads
  3. Veți vedea trei sub-secțiuni:
    • Speculation Rules: Regulile detectate pe pagină
    • Preloads: Speculările active și starea lor
    • This Page Was Prerendered: Apare dacă pagina curentă a fost pre-randată

Pentru fiecare speculare, DevTools raportează starea: „Not triggered", „Pending", „Running", „Ready", „Success" sau „Failure" cu motivul eșecului. Super util pentru debugging.

Strategii pentru E-Commerce

Site-urile de e-commerce sunt candidații perfecți pentru Speculation Rules API. Gândiți-vă: utilizatorii navighează între zeci de produse, compară, revin la categorii — fiecare tranziție instantanee e un pas mai aproape de conversie.

Iată o strategie completă:

<script type="speculationrules">
{
  "prerender": [
    {
      "source": "document",
      "where": {
        "and": [
          { "selector_matches": ".product-card a" },
          { "not": { "selector_matches": ".out-of-stock a" } }
        ]
      },
      "eagerness": "moderate"
    },
    {
      "source": "document",
      "where": { "selector_matches": ".category-nav a" },
      "eagerness": "eager"
    }
  ],
  "prefetch": [
    {
      "source": "document",
      "where": {
        "or": [
          { "href_matches": "/cos/*" },
          { "href_matches": "/finalizare-comanda/*" }
        ]
      },
      "eagerness": "conservative"
    }
  ]
}
</script>

Ce face: pre-randează paginile de produs (cele mai accesate) la hover, pre-randează proactiv navigarea categoriilor și face doar prefetch pentru paginile cu stare. Rezultatul? Navigarea între produse devine instantanee, îmbunătățind semnificativ experiența de cumpărare.

Considerații Importante și Limitări

Consumul de Resurse

Prerendering-ul consumă memorie și bandwidth — nu e gratuit. Câteva recomandări practice:

  • Chrome limitează automat numărul de pagini pre-randate simultan (de obicei la 2)
  • Folosiți eagerness: "moderate" sau "conservative" pe paginile cu multe link-uri
  • Evitați prerendering-ul pe conexiuni lente — Chrome respectă automat indicatorul Save-Data
  • Monitorizați consumul de bandwidth în analytics pentru a ajusta strategia

Pagini cu Efecte Secundare

Nu pre-randați pagini care au efecte secundare la încărcare. Serios, asta poate cauza probleme reale:

  • Pagini care trimit analytics la DOMContentLoaded (ar dubla vizualizările)
  • Pagini care modifică starea serverului (marcarea notificărilor ca citite, de exemplu)
  • Pagini cu formulare care generează token-uri CSRF la încărcare

Puteți verifica în JavaScript dacă pagina rulează ca prerender:

if (document.prerendering) {
  // Pagina rulează în fundal ca prerender
  // Amânați efectele secundare
  document.addEventListener("prerenderingchange", () => {
    // Acum pagina e vizibilă — executați efectele secundare
    sendPageViewAnalytics();
    initializeChat();
  });
} else {
  // Navigare normală
  sendPageViewAnalytics();
  initializeChat();
}

Cross-Origin și Securitate

Speculation Rules API respectă restricții de securitate importante (și pe bună dreptate):

  • Prerendering-ul cross-origin necesită un header Supports-Loading-Mode: credentialed-prerender pe serverul destinație
  • Paginile cu Cache-Control: no-store nu pot fi pre-randate
  • Browser-ul anulează automat prerendering-ul dacă pagina încearcă să acceseze API-uri restricționate (geolocation, notificări)

Integrarea cu Framework-uri Populare

Next.js

Pentru aplicațiile Next.js (Pages Router sau App Router cu SSG/SSR):

// components/SpeculationRules.tsx
export default function SpeculationRules() {
  const rules = {
    prerender: [{
      source: "document",
      where: {
        and: [
          { href_matches: "/*" },
          { not: { href_matches: "/api/*" } },
          { not: { href_matches: "/_next/*" } }
        ]
      },
      eagerness: "moderate"
    }]
  };

  return (
    <script
      type="speculationrules"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(rules) }}
    />
  );
}

// Adăugați în layout.tsx sau _document.tsx
// <SpeculationRules />

Astro

Astro are suport nativ experimental — configurarea e minimală:

---
// astro.config.mjs
import { defineConfig } from "astro/config";

export default defineConfig({
  prefetch: {
    prefetchAll: true,
    defaultStrategy: "viewport"
  },
  experimental: {
    clientPrerender: true
  }
});
---

WordPress

WordPress include din versiunea 6.8 suport nativ pentru Speculation Rules API. Puteți activa funcționalitatea din setări sau adăuga manual regulile:

// functions.php
add_action("wp_head", function() {
  if (!wp_is_mobile() || !is_admin()) {
    echo "<script type=\"speculationrules\">";
    echo json_encode([
      "prerender" => [[
        "source" => "document",
        "where" => [
          "and" => [
            ["href_matches" => "/*"],
            ["not" => ["href_matches" => "/wp-admin/*"]],
            ["not" => ["href_matches" => "/wp-login.php"]]
          ]
        ],
        "eagerness" => "moderate"
      ]]
    ]);
    echo "</script>";
  }
});

Checklist Final de Implementare

Înainte de a lansa în producție, treceți prin această listă. Am învățat pe propria piele că sărirea peste vreun pas se plătește mai târziu:

  1. Identificați paginile potrivite: Analizați fluxul de navigare din analytics — care sunt cele mai frecvente tranziții între pagini?
  2. Alegeți strategia: Prerender pentru paginile statice/de conținut, prefetch pentru cele cu stare.
  3. Setați eagerness corect: moderate sau conservative pentru majoritatea cazurilor. eager doar pentru navigarea principală.
  4. Excludeți paginile problematice: Logout, admin, checkout, pagini cu efecte secundare.
  5. Optimizați bfcache: Eliminați unload handlers, evitați Cache-Control: no-store pe paginile de conținut.
  6. Protejați analytics-ul: Verificați document.prerendering înainte de a trimite page views.
  7. Implementați progressive enhancement: Verificați suportul browser-ului și oferiți fallback.
  8. Testați în DevTools: Folosiți Application > Speculative loads pentru a verifica regulile.
  9. Monitorizați în producție: Urmăriți LCP, INP și CLS cu Real User Monitoring.
  10. Iterați: Ajustați regulile pe baza datelor reale. Performanța web nu e un proiect cu dată de final — e un proces continuu.

Concluzie

Speculation Rules API, combinată cu o optimizare atentă a bfcache, e cea mai eficientă modalitate de a oferi navigare instantanee pe web în 2026. Și rezultatele chiar sunt impresionante: reduceri de sute de milisecunde în LCP, navigări înapoi/înainte instantanee și o experiență comparabilă cu aplicațiile native.

Ce e frumos e că adoptarea e progresivă și sigură. Browserele care nu suportă API-ul pur și simplu ignoră tag-ul <script type="speculationrules">, iar utilizatorii pe Chrome, Edge și Opera beneficiază imediat. Cu semnele de adoptare cross-browser din 2026, acum e momentul perfect să implementați aceste tehnici.

Recomandarea mea: începeți cu o implementare minimă (prefetch cu eagerness moderate), măsurați impactul, apoi extindeți către prerendering pentru paginile cu cel mai mare trafic. Combinați cu optimizarea bfcache și veți obține o experiență de navigare pe care utilizatorii o vor aprecia imediat — chiar dacă nu pot identifica exact ce s-a schimbat. Și asta, de fapt, e magia performanței web: când funcționează bine, nimeni nu o observă.

Despre Autor Editorial Team

Our team of expert writers and editors.