← Back to list

How to Make Your Website Feel Instant by adding a few lines of HTML

Using the Browser Feature Speculation Rules

Hamid Reza Salimian · 2026-06-28 19:18 · 7 claps · 10.2 min read
#speculation #chrome #page-speed #optimization #seo
Open on Medium ↗
Wiki topics: SEO · SEO & SEM 🌐 · Web Development

How to Make Your Website Feel Instant by adding a few lines of HTML

Using the Browser Feature Speculation Rules

You know that delay between clicking a link and the new page showing up? Now imagine you click on a link and instantly it will show up, magic? No, they have already been loaded! …. how?

Speculation Rules is a way to make that delay (almost) disappear, by quietly getting the next page ready before the user even clicks. You add a few lines of code to your HTML, and supporting browsers start loading the pages a user is likely to visit next, in the background. The result is faster navigation, a smoother feel, and better Core Web Vitals scores (Google measured real improvements of around 60 milliseconds in load times on their own search results).

But I’m here also to notice that loading pages early costs bandwidth and memory, and some pages are not safe to load early (think “log out” or “add to cart” links).

So the real skill is choosing what to speculate on and how eagerly. Let’s break it all down.

I’ve described it into 7 parts,

  1. How it works
  2. The two types: prefetch vs prerender (How fetch other pages)
  3. How eager should the browser be? ( When fetch other pages)
  4. Caveats of using it
  5. What about Next.js? It already does this, but differently
  6. Simple Benchmark: How much faster is it, really?
  7. FAQ

1. How it works

Normally, a navigation looks like this: the user clicks, then the browser asks the server for the page, waits, and renders it. The user stares at a blank or loading screen the whole time.

Speculation Rules flips the order. While the user is still reading the current page, the browser is already fetching the next one. By the time they click, the work is done.

Without speculation, all the work happens after the click. With it,

Without speculation, all the work happens after the click. With it,

The work happens before, so the click feels instant.

You turn this on by dropping a small <script> block into your HTML. The browser reads the rules and decides what to load early:

<script type="speculationrules">
{
  "prerender": [
    {
      "where": { "href_matches": "/*" },
      "eagerness": "moderate"
    }
  ]
}
</script>

That’s it. This example tells the browser:

for any link on this page- > get it ready, when the user looks like they’re about to click it.

2. The two types: prefetch vs prerender

Speculation Rules gives you two levels of “getting ready.” They differ in how much work the browser does ahead of time.

Prefetch is cheap and quick. Prerender is expensive but gives a near-instant result.

Prefetch is cheap and quick. Prerender is expensive but gives a near-instant result.

Prefetch

Just downloads the next page’s HTML document — nothing else. No images, no CSS, no JavaScript is run yet. It is cheap, so you can use it generously across your site. When the user clicks, the page still has to finish loading its other files, but it already has a big head start.

Prerender

Goes all the way → 1. The browser fetches the page + 2. fully builds it in an invisible background tab, including running its JavaScript, loading its images, everything.

When the user clicks, the browser simply swaps in the already-built tab, so the page appears almost instantly. The cost is much higher (roughly the same as loading an <iframe>), so you should use it wisely, only for pages a user is very likely to visit.

A simple way to remember it: prefetch is grabbing the ingredients; prerender is cooking the whole meal in advance.

Done? … no, still you can config it ;)

3. How eager should the browser be?

Getting a page ready early is helpful, but doing it for every link the moment a page loads would waste a lot of data on links nobody clicks. The eagerness setting lets you control when the browser acts. There are four levels.

Eagerness is a trade-off: act early and you get more lead time but waste more; act late and you waste less but the page may not be fully ready in time.

Eagerness is a trade-off: act early and you get more lead time but waste more; act late and you waste less but the page may not be fully ready in time.

  • **immediate** — Get ready right away, as soon as the rules are read. Most lead time, most potential waste.
  • **eager** — Almost as keen as immediate (today it behaves the same in Chrome). Meant for "very likely" links.
  • **moderate** — Get ready when the user hovers over a link for about 200 milliseconds, or presses down on it. This is the wise and cautious spot for most sites: hovering is a strong hint the user is about to click.
  • **conservative** — Wait until the user actually presses down on the link!! Least waste, almost useless! But the shortest head start.

A great default for many sites is prerender with moderate eagerness on internal links — it costs almost nothing until a user shows real intent, then makes the click feel instant.

Good to know: browsers also protect users automatically. Chrome won’t speculate when the device is in Data Saver or battery-saver mode, when memory is low, when the “*Preload pages*” setting is off, or for pages sitting in background tabs. It also limits how many pages it will get ready at once (for example, only 2 at a time for moderate/conservative rules).

4. When to use which — and when NOT to

This is where most of the real thinking happens. Loading pages early is not free, and some pages are genuinely dangerous to load before the user means to visit them.

A simple rule

  • Prefetch broadly. The cost is low, so prefetching most of your important pages (with moderate eagerness) is usually a safe win.
  • Prerender selectively. Save it for pages you’re confident the user will visit, the very next step in a flow, the top search result, the “next” button in an article series.
  • Use eagerness to control waste. Heavier pages and bigger sites should lean toward moderate or conservative. Light, static sites can afford to be more eager.

Match the technique to how confident you are and how heavy the page is , and keep risky URLs out entirely.

Match the technique to how confident you are and how heavy the page is , and keep risky URLs out entirely.

The danger zone: pages you should NOT speculate on

When the browser fetches a page early, it sends a real request to your server. If that URL does something just by being visited, you have a problem. Avoid speculating on:

  • Log-out URLs: the user gets silently signed out.
  • “Add to cart” or “buy” URLs: items get added without a real click.
  • Language- or theme-switching URLs: settings change unexpectedly.
  • One-time-password / “send SMS” URLs: a text gets sent before the user asked.
  • Usage-counting URLs: like “you’ve read 1 of 3 free articles,” which would tick down wrongly.
  • Ad-conversion or analytics URLs: your numbers get polluted with visits that never happened.

If a link only changes things through JavaScript that runs after the click, it’s usually safe, because that JavaScript doesn’t run during a prefetch, and even better that it’s held back until activation during a prerender

How to exclude links?

You can also tell the browser to skip specific links, for example by excluding them in your rule ("not": { "href_matches": "/logout" }) or by detecting the request on the server (it arrives with a Sec-Purpose: prefetch header) and responding accordingly.

5. What about Next.js? It already does this — but differently

If you build with Next.js, you may have noticed navigation already feels fast. That’s because the <Link> component prefetches automatically.

But it is not the browser's Speculation Rules API — it's Next.js's own system, working at a different layer.

Same goal — instant navigation — but Speculation Rules works at the browser level.

Same goal — instant navigation — but Speculation Rules works at the browser level.

Speculation Rules is a browser feature that loads (and can fully prerender) entire HTML pages, which suits classic multi-page sites.

Next.js, on the other hand, behaves like a single-page app: clicking a link doesn’t reload the whole page, it swaps content in place. So instead of fetching a full page, Next.js prefetches just the route’s data and JavaScript bundle (its React Server Component payload) needed to render the next view.

A few things to know about Next.js prefetching:

  • It happens automatically when a <Link> scrolls into view (it uses the browser's Intersection Observer), and again on hover if the data has gone stale.
  • It only downloads the code and data — it doesn’t run it — so it won’t trigger side effects on the destination page.
  • For static routes it prefetches the full route; for dynamic routes it prefetches a partial version down to the nearest loading.js boundary, so you still get an instant loading state.
  • You control it with the prefetch prop: null/auto (the smart default), true (always prefetch the full route), or false (never).
  • It only runs in production, so you won’t see the effect in next dev.
import Link from 'next/link'

// Prefetches automatically when it enters the viewport
<Link href="/dashboard">Dashboard</Link>

// Turn prefetching off for a rarely visited or heavy page
<Link href="/huge-report" prefetch={false}>Annual Report</Link>

So which should you use?

If you’re on Next.js (or a similar framework), let its built-in <Link> prefetching handle your in-app navigations — that's what it's designed for. The two aren’t enemies;

some frameworks (like Astro) have even started adding experimental Speculation Rules support on top of their own prefetching.

6. Simple Benchmark: How much faster is it, really?

The honest answer is it depends on your server, your page weight, and the user’s device and network. But here’s how to think about it concretely.

An illustrative example. Picture a normal website. A fresh navigation, the gap between clicking a link and the page actually being usable, takes around 800 ms (server response + downloading the HTML + loading the page’s images, CSS and JavaScript). Here’s what the user feels on a single click:

cross a visit, prefetch roughly halves the waiting and prerender almost removes it. (Illustrative numbers — yours will differ.)

cross a visit, prefetch roughly halves the waiting and prerender almost removes it. (Illustrative numbers — yours will differ.)

  • Without speculation: about 800 ms of waiting.
  • With prefetch: about 450 ms; the HTML is already downloaded, so you skip that round-trip (~350 ms saved).
  • With prerender: about 80 ms; the page is already built, so the click just swaps it in (~720 ms saved).

Now picture a real visit. The user lands on a page with 10 links and clicks through 5 of them. The waiting adds up:

  • Without speculation: about 4.0 seconds spent staring at loading screens.
  • With prefetch: about 2.3 seconds (~44% less).
  • With prerender: about 0.4 seconds (~90% less), navigation feels basically instant.

Measure it on your own site:

  • In Chrome, open DevTools → Application → Speculative loads → Speculations, then hover over links and watch pages get prefetched or prerendered live.

  • Compare the LCP (Largest Contentful Paint) of a normal navigation against a speculated one, using the DevTools Performance panel or the Web Vitals extension.
  • Or just feel the difference on Chrome’s live demo at chrome.dev/speculative-loading. and see the Network tab

7. Frequently asked questions

1. Does a prefetch or prerender count as a hit in Google Analytics? What about my own server-side analytics?

The short version: modern client-side analytics won’t be fooled, but your server logs will, so filter them.

  • Google Analytics 4, gtag.js and Google Tag Manager are “prerender-aware.” When a page is prerendered, they hold the pageview back and only send it once the user actually opens the page , so you don’t get phantom visits. A prefetch runs no JavaScript at all, so nothing fires until the user navigates. Either way, you record one real pageview at the moment the user arrives, not before.
  • Older or custom client-side analytics can over-count if they fire the moment their script runs without checking whether the page is still hidden. The fix is to make them prerender-aware: check document.prerendering and wait for the prerenderingchange event before sending anything.
  • Your server-side/internal analytics will see the extra requests, because a speculation is a real request to your server. To avoid counting loads the user never saw, check the Sec-Purpose request header, speculative requests include it (it contains prefetch, plus prerender for prerenders) — and either skip logging them or tag them as speculative.

2. Doesn’t only Chrome support it?

Right now, yes, it works in Chromium-based browsers (Chrome, Edge, Opera, and the like). Firefox and Safari don’t support it yet. But that’s not a reason to avoid it, because it’s a progressive enhancement: browsers that don’t understand the <script type="speculationrules"> block simply ignore it, so those users just get the normal experience and nothing breaks. Since Chromium browsers make up the majority of web traffic, a large share of your visitors get the speed-up for free today, and other browsers may add support later — it's on the standards track.

3. If I set eagerness to "immediate”, will it load every page behind every link at once? And does that affect my current page's load event?

Two separate things are bundled in here:

  • It won’t literally load all links, but immediate is aggressive. It starts loading the matching pages straight away, up to Chrome's safety caps (around 50 prefetches or 10 prerenders at a time). Prerendering 10 pages is heavy — it's roughly like opening 10 hidden tabs, so immediate combined with prerender across many links wastes a lot of data and memory. Use immediate or eager only for a page you're confident about (like the obvious next step), and use moderate when your rule matches "any link on the page," so loading only starts when the user hovers or presses.
  • Your current page’s load event is not affected. Speculation loads other pages in the background at a lower priority, so the page the user is on loads and fires load exactly as before. The thing to watch is the destination page: when it's prerendered, its own DOMContentLoaded and load events fire while it's still hidden, before the user clicks. So if you have code in load that should only run once the page is actually visible (starting a video, an animation, a counter, sending a beacon), guard it with document.prerendering and the prerenderingchange event so it waits for activation. A prefetched page runs no JavaScript until the user navigates, so its load fires normally.

4. Will it slow down my laptop or eat up my internet bandwidth?

It does use some bandwidth and memory, prerender more so, since a fully built hidden page costs roughly as much as an extra tab. But it’s built to be polite:

Speculative loads are fetched at lower priority, so they don’t slow down the page you’re currently viewing.

  • The browser skips speculation automatically when it shouldn’t spend resources: Data Saver mode, battery/energy-saver mode, low device memory, the user’s “Preload pages” setting being off, and pages sitting in background tabs.
  • The browser limits how many pages it prepares at once. (around 50 prefetches or 10 prerenders at a time).

So let’s make our pages feel faster for users ;)


메타데이터
post_id
f2b718e4b7a8
slug
how-to-make-your-website-feel-instant-by-adding-a-few-lines-of-html-f2b718e4b7a8
url
https://medium.com/@salimian/how-to-make-your-website-feel-instant-by-adding-a-few-lines-of-html-f2b718e4b7a8
canonical_url
https://medium.com/@salimian/how-to-make-your-website-feel-instant-by-adding-a-few-lines-of-html-f2b718e4b7a8
author_url
https://medium.com/@salimian
status
ok
fetched_at
2026-07-09 15:12:33