Prefetching is supposed to improve performance, but it can sometimes delay how quickly your website loads.
Learn what the advantage of resource prefetching is, how it can cause performance issues, and what you can do about it.
The promise of resource prefetching
Prefetching is a web performance technique that involves speculatively loading resources before they are needed.
For example, when someone visits your homepage you might prefetch code that's used on the login or pricing pages. Then, when the visitor does visit those pages they will load more quickly as the necessary resources are already available.
To prefetch a resource you add a prefetch link tag to your HTML code:
<link rel="prefetch" as="style" href="page-2.css" />
Prefetch request priority
Prefetched resources aren't needed right away, so they should load quietly in the background. Google explains this on web.dev:
The browser queues up all hints and requests each resource when it's idle.
Prefetching takes place at the 'Lowest' priority, so prefetched resources don't compete for bandwidth with the resources required in the current page.
Early prefetch requests causing bandwidth competition
Unfortunately, when looking at request waterfalls showing how resources load on our website, we often found that the prefetch requests were happening early and competing for bandwidth with our main content image.
Even though Chrome marks the prefetch requests as lowest priority, our high priority Largest Contentful Paint image was not downloaded quickly.
In theory the server should also be aware of the priority and send important resources first, but in practice many cloud providers don't support this correctly.
Is this impacting real users?
Lab-based performance tests are run in an artificial environment that often doesn't match what real users experience. For example, most visitors have a faster connection with more available bandwidth than is used when running tests with Google's Lighthouse tool.
So we set up real user monitoring to track the load time for the image and the first prefetched JavaScript file. It turned out that it was more common for the prefetch to finish before the image than the other way round!
Note that regardless of prioritization, the prefetched JS has an advantage as it's loaded from the same domain as the HTML document, while the image requires a new server connection.
Does performance improve when prefetching is disabled?
Did loading the prefetched files early impact how long visitors wait to see page content? We started serving the prefetch link tags only half the time to measure the impact.
We didn't see a huge difference, though the 75th percentile LCP score was 100 milliseconds better without the prefetch.
This matched at the 90th percentile, though at the 95th percentile page views with JavaScript prefetching were faster 🤷♂️
Is it common for prefetched resources to load early?
When looking for examples of websites that use prefetching it was difficult to find a website where prefetching happens when the network is idle.
Ideally the browser would only prefetch resources once the main page content has rendered. The example below shows that lowest-priority JavaScript is loaded much earlier.
Note that this doesn't necessarily mean the LCP will be delayed. A bunch of processing and resource loading is happening on the page, and using a little bit of bandwidth for prefetching isn't necessarily bad. Still, it seems odd for prefetched files to start loading less than a second after the page was opened!
I also found an example of a website prefetching over a megabyte of content prior to the Largest Contentful Paint. However, it consisted of many 10 KB images, so it was hard to take a screenshot of the request waterfall!
How to prevent prefetching from slowing down your website
To make sure prefetched resources don't compete with more important content, don't put prefetch hints into the initial page HTML or HTTP headers.
Instead, insert them into the page later on using JavaScript. Like this for example:
window.addEventListener("load", () => {
const link = document.createElement("link");
link.as = "style";
link.rel = "prefetch";
link.href = "page-3.css";
document.head.appendChild(link);
});
Conclusion
Prefetched resources are often loaded early and can compete with the resources that are needed to display the page content. However, performance often isn't constrained by the available bandwidth, so in many cases the page speed impact will be negligible.
Chrome could handle prefetching better by waiting until the page has finished loading. When testing in Firefox I found that prefetch requests are held back for longer, giving the primary page content a chance to render first.