The new "Speculation Rules API" is changing everything
4 minutes read time · 628 words · Tutorial
4 minutes read time · 628 words · Tutorial
One of the easiest ways to improve your site is to make it load faster. But this is easier said than done, especially when you start dealing with prefetching and prerendering. Things can get complicated with lazy loading and other optimizations.
However, with the new Speculation Rules API built into the browser, you no longer need to worry. But before we continue, there are a few catches you need to understand before implementing this on your website.
I'll be covering all the new features and potential pitfalls of the Speculation Rules API and helping you make your website faster.
Before we dive in, let's first take a look at a Basic Demo I've set up. We'll use this example to explore different ways to implement the Speculation Rules API and optimize performance.
For this project, we will be disabling the cache. This will simulate how the website appears when a visitor accesses it for the first time. Additionally, we can change the Network setting to Fast 4G to get a more realistic view of performance.
When clicking the links, you’ll notice a slight delay in loading the webpage, and images may flash briefly. This is exactly what we want to avoid. Instead, we want to prerender or prefetch content to create a smoother and faster transition between pages. These are two different techniques that significantly improve page-loading speed and user experience.
This optimization is achieved using the Speculation Rules API.
Currently, availability is somewhat limited since this is a relatively new feature, but it is expected to roll out to more browsers in the near future.
There are two different types of Speculation Rules: prefetch
and prerender
.
Here’s an example of how this can look:
<script type="speculationrules">
{
"prerender": [
{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": { "href_matches": "/logout" } },
{ "not": { "href_matches": "/*\\?*(^|&)add-to-cart=*" } },
{ "not": { "selector_matches": ".no-prerender" } },
{ "not": { "selector_matches": "[rel~=nofollow]" } }
]
}
}
],
"prefetch": [
{
"urls": ["next.html", "next2.html"],
"requires": ["anonymous-client-ip-when-cross-origin"],
"referrer_policy": "no-referrer"
}
]
}
</script>
📌 Note: Future updates may allow a src attribute in the <script> tag to reference an external JSON file, but currently, you must define rules inline.
When using prefetch it tries getting all the links which has the url that you set and tries to load all HTML. But no CSS, images, Javascript or CSS. When you want this to render too you will need to use prerender
prefetch Example:
<script type="speculationrules">
{
"prefetch" : [
{ "urls" : [ "/", "/about.html", "/contact.html" ] }
]
}
</script>
By including this script on all the specified pages, we tell the browser to start fetching the HTML of these pages as soon as possible. While the effect might not be instantly noticeable, you can verify whether it works by opening the Application tab in your browser’s developer tools (F12) and checking under Speculative Loads.
Not all browsers support speculationrules
, and in some cases, you might see an error message indicating this. If successful, the speculative load status should display as Ready, confirming that the pages have been preloaded.
Prerendering takes things a step further. Instead of just downloading the HTML, it fully loads the page, including CSS, JavaScript, and images. This means that when the user actually visits the page, everything is already in place, making the transition feel instantaneous.
One thing to keep in mind is that prerendering can cause unintended effects. For example, if you use web analytics, a prerendered page might register as a visited page even if the user never actually opened it. To prevent this, you can ensure scripts only execute when the page is fully loaded.
Handling Prerender Execution:
if (document.prerendering) {
document.addEventListener("prerenderingchange", main, { once: true })
} else {
main()
}
function main() {
setTimeout(() => {
document.body.append("Timeout Finished")
}, 1000)
}
A way to prerender a website on hover is adding a eagerness
. You can add moderate for example. This will render MAX 2 pages. So if you open another page, the first last rendered file/page will be removed of the prerender.
Sources