Telerik blogs

Learn how to prerender and prefetch using the Speculation Rules API to improve the performance of your site.

Prerendering is a common pattern used to speed up web applications. It’s a technique that some browsers (e.g., Chrome) and JavaScript frameworks (e.g., Next.js) use to improve the loading performance of a webpage.

Every page in Next.js’s pages router is pre-rendered by default. This means that it generates HTML for each page in advance, instead of relying entirely on client-side JavaScript. Chrome supported the <link rel="prerender" href="/next-route"> resource hint, but it was not broadly supported beyond Chrome.

While Chrome, Next.js and others have evolved how they apply this pattern, it demonstrates that prerendering can result in better performance and improved SEO.

Prerendering techniques in JavaScript frameworks are unique to each framework, and Chrome’s <link rel="prerender" /> has been deprecated in favor of NoState Prefetch. However, there’s a better way, one that’s becoming part of the Web Platform API—the Speculation Rules API.

Introducing the Speculation Rules API

The Speculation Rules API is a recent browser feature that lets you tell the browser which pages to fetch or render in the background, thereby improving the next navigation speed. Put another way, you define a set of rules that the browser uses to predict when a page should be fetched or prerendered, before the user actively navigates to that page.

It is explicitly designed for multi-page websites (MPAs) rather than single-page apps (SPAs). If you’re building an SPA, you should use your framework’s prefetch or prerender API.

There are two types of speculative actions (or loading types):

  1. Prerendering: This downloads the resources for a page and renders the page in the background. The rendered page is instantly displayed when the user navigates to it.
  2. Prefetching: This fetches key resources for a page but doesn’t render the page. The page still needs to be rendered when the user navigates to it.

Speculation rules are useful any time you can predict which page a user is likely to visit next. Common scenarios for using them include ecommerce and media sites. For example, prerendering a product detail page or prefetching the resources for the checkout page. The same idea applies to a documentation site, where eagerly prerendering the next page will make it load instantly when the user navigates to it. This can improve Core Web Vitals (like LCP) on these navigations and often boosts engagement.

Anatomy of Speculation Rules

Speculation rules are written in JSON, inside a <script type="speculationrules"> block in your HTML or in an external JSON file referenced via the Speculation-Rules HTTP header. The JSON has separate keys for "prefetch" and "prerender", which represent the two types of speculative loading. They each map to an array of rule objects. For example:

<script type="speculationrules">
{
  "prerender": [
    { "urls": ["/blog", "/newsletter"] }
  ],
  "prefetch": [
    { "urls": ["/contact.html"] }
  ]
}
</script>

In this snippet, two URLs (/blog and /newsletter) are listed under prerender, and one URL (/contact.html) under prefetch. The prerender rule causes the browser to fully render those pages in the background, while a prefetch rule only fetches the HTML.

The urls list (as seen in the example) will be activated immediately upon parsing. The browser assumes they’re high-priority URLs that you want to make available as soon as possible. My rule of thumb is to always specify the eagerness property to make it explicit to other developers and the browser.

The eagerness property specifies what heuristics the browser should use to determine when to apply the rule. The options are:

  1. immediate: Prefetch/prerender should start as soon as possible.
  2. eager: Prefetch/prerender should start on any slight suggestion that a link may be followed. For example, moving the cursor toward the link or scrolling the section of the link into the viewport.
  3. conservative: Used when you wish to get some benefit but with a fairly small tradeoff of resources. The speculative action should start only when the user is starting to click on the link, for example, on the mousedown event.
  4. moderate: Strikes a balance between eager and conservative.

Real-world Example

There are many rules beyond what you saw in the last section, and I won’t cover them all in detail. Let’s look at a practical example and revisit the rules later. We will use my website pmbanugo.me as an example. There are a few important routes:

  1. The Home page.
  2. The Blog listings page (/blog), which shows the list of blog posts, as well as navigation.
  3. The Blog post page (/blog/:), which contains the content of the actual posts.

I want to use speculative loading to prerender them. I want to eagerly load the home and the blog listings pages because they’re typically the next pages that my website visitors go to. The blog post page (/blog/:) will use the moderate algorithm.

Shows how users navigate the website. They typically come in via a blog post, then navigate to the home or blog listing pages.

Here’s how we’re going to define the rule for that requirement:

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

The where property specifies the filter applied when searching the document for links that meet the criteria. The href_matches specifies a URL pattern that will be used for filtering. In summary, the browser will scan the page for links matching that URL pattern, then prerender them when there’s a hint that the user is about to navigate to that page.

Let’s review the loading performance of pmbanugo.me before we apply the change. The video recording below shows me browsing through the site with the browser cache disabled.


I throttled the performance to a Fast 4G connection so that we can see how it works without the usual browsing speed of my home internet. I’ll do the same for the version with speculation rules.


The video above shows the same navigations but using speculation rules. You may notice that despite being throttled to Fast 4G, the pages load instantly. For the /blog/:<slug> page, I waited a bit before clicking. This gives it enough time to fetch and render under the throttled condition. Otherwise, requests for resources may still be in flight, and the page may not yet be prerendered.

You may need to inspect how your speculation rules are behaving. This will differ between browsers and may change over time. The screenshot below shows how it looks in Chrome 136.

Shows how the speculation rules are applied. You can see which resource was prefetched or prerendered.

The dropdown shows the current document with the title Main. Any other resource that’s prefetched or prerendered will display the resource path and the speculation action. In this example, blog/top-x-react-ui-library was prerendered.

The video below shows the behavior of the speculation rules and the associated network/performance effect. You should also notice that the navigations happen instantly.

Hint: Pay attention to the DevTools window.


More Rule Properties

I mentioned a few rules from the example you saw. There are more rules, and I can’t use them all in my example. Each rule object can include several properties to control when and how the loading happens. Some important rule properties are:

  • urls: An array of string URLs to be prefetched/prerendered.
  • where: An object to filter links on the page (used in document rules). It can use conditions like href_matches (with wildcards), selector_matches (CSS selectors) and logical wrappers and / or / not to include or exclude certain links. For example, { "where": { "href_matches": "/blog/*" } } would match all same-origin links under /blog/.
  • eagerness: This controls when to trigger speculation. Options are "immediate", "eager", "moderate" or "conservative". For instance, "immediate" fires as soon as the rule is parsed, while "moderate" waits until the user hovers over a link for ~200ms (or mouse-down). URL-list rules use immediate by default.
  • requires: An array of requirement strings, e.g., "anonymous-client-ip-when-cross-origin", which enforces privacy settings. It strips off the client IP on cross-site requests.
  • referrer_policy: A string like "no-referrer" to control the Referer header on the speculative requests.
  • relative_to: A string specifying where you want links matching a URL to be matched relative to.
  • expects_no_vary_search: A caching hint used when query parameters do not actually change the content.
  • tag: A string used to identify a rule or ruleset. It could be useful for debugging.
  • source: An optional property indicating the source of the URLs to which the rule applies. The value can be either "list" or "document".

That’s a Wrap

Speculation rules are a new way for developers to tell browsers to load resources early, before the user actually requests them. They improve your website’s performance and can lead to higher retention and customer conversion. They offer two speculative loading patterns—prefetch and prerender. We looked at what they are and focused the example on a few rules and the prerender pattern.

You’re probably excited to use them based on what you saw from the demos/videos. Take note that they’re not implemented across all browsers yet. They’re available in Chromium-based browsers like Chrome, Edge and Opera. When you use them, consider providing alternatives to users on browsers where they’re not supported. The links below contain more info:

  • Speculation Rules API (MDN)
  • Detailed rule specification (MDN)
  • Browser Compatibility (MDN)
  • Specification Draft by Web Platform Incubator Community Group.

Peter Mbanugo
About the Author

Peter Mbanugo

Peter is a software consultant, technical trainer and OSS contributor/maintainer with excellent interpersonal and motivational abilities to develop collaborative relationships among high-functioning teams. He focuses on cloud-native architectures, serverless, continuous deployment/delivery, and developer experience. You can follow him on Twitter.

Related Posts

Comments

Comments are disabled in preview mode.