We use every trick in the book to speed up our websites. Optimizing images. CDNs. GZIP. Caching. But as sites become more complex and burdened by page weight, reactively responding to user interactions is not enough. We need to be proactive—we need to predict what users want, and even get that content ready for them before they ask for it.
With resource hints and directives, you can do just that—tell browsers to fetch and download resources for your pages ahead of time for better actual and perceived website performance. This technique is known as prebrowsing.
In this post, we’ll explore three key resource hints: preload, prefetch, and preconnect, along with how they work, their benefits, and how to use them.
What is Prebrowsing?
Steve Souders coined the term prebrowsing (from predictive browsing) in 2013.
Prebrowsing is all about anticipating user actions and preparing content on your site that they might want before they actually need it. It’s a concept that’s a step toward a faster internet, as A List Apart’s Santiago Valdarrama writes in his article, One Step Ahead: Improving Performance with Prebrowsing:
“Browsers are already working behind the scenes, looking for patterns in our sites to make navigation as fast as possible. Prebrowsing builds on that: we can combine the insight we have on our own pages with further analysis of user patterns. By helping browsers do a better job, we speed up and improve the experience for our users.”
You might be wondering, “isn’t this what caching is for?” Well, yes. Browser caching is essential for the fast loading of pages. But there are times when caching needs a little help:
- First-time website visits: The first time a user visits a site, their browser hasn’t cached any static resources yet.
- Cleared browser data: Users who clear their browser cache will no longer have a copy of your resources the next time they visit your site.
- Expired browser data: According to HTTP Archive, 69% of resources don’t have any caching headers or are cacheable for less than one day. If the user revisits these pages and the browser determines the resource is expired, an HTTP request is needed to check for updates. Even if the response indicates the cached resource is still valid, these network delays still make pages load more slowly, especially on mobile.
- Old browser data: Even if a user has cached content from a previous visit, the website might have changed or been updated with new resources.
Fortunately, prebrowsing techniques can help you get around these issues.
Have you ever wanted to tell the browser about an important font or script without delaying the page’s onload event?
With preload, you can do just that. This directive tells the browser that a resource is needed as part of the current navigation, and that it should start being fetched as soon as possible.
Here’s an example of how to use it:
As Yoav Weiss, a principal architect at Akamai who worked on this web standard, explains:
“[Preload provides] more granular loading control to web developers. It gives developers the ability to define custom loading logic without suffering the performance penalty that script-based resource loaders incur.”
The as attribute tells the browser what type of resource it will be downloading so it can be handled correctly. Without it, the browser won’t use the preloaded resource. Possible values include:
<link rel=”preload”> supersedes <link rel=”subresource”>, which, according to Google, had significant bugs and drawbacks. It was never implemented in browsers other than Chrome. As such, Chrome 50 removed support for it in March 2016.
It’s also important to know preload is a compulsory instruction to the browser. Unlike the other resource hints we’ll look at in this post, preload is something the browser must do, rather than optionally.
Weiss published a definitive guide to preload prior to its release in Chrome. If you’re interested in learning how to use this resource hint effectively, I highly recommend reading his guide.
Think you can predict what the user will click or interact with next?
The prefetch resource hint is somewhat different to preload. It doesn’t try to make something critical happen faster; rather, it tries to make something non-critical happen earlier—if there’s a chance.
With prefetch, you can tell the browser to fetch resources you think the user might need later as part of a future navigation or interaction, if the user takes the action you’re expecting. These resources will then be fetched at the lowest priority in the browser, when the current page is done loading and there’s bandwidth available.
This means that prefetch is best used to anticipate the user’s next action and prepare for it, such as retrieving necessary scripts or images.
There are 3 types of prefetching, and what I’ve described above is typically known as link prefetching.
According to Mozilla’s MDN web docs for link prefetching:
“… After the browser is finished loading the page, it begins silently prefetching specified documents and stores them in its cache. When the user visits one of the prefetched documents, it can be served up quickly out of the browser’s cache.”
For this type of prefetching, the browser looks for prefetch either in an HTML <link> or an HTTP Link: header. Here’s an example using the link tag:
And here’s the same link prefetching hint using an HTTP Link: header:
The other 2 other types of prefetching are DNS prefetching and prerendering.
DNS prefetching lets you tell the browser to perform DNS lookups on a page in the background while the user is browsing. So by the time the user clicks a link as anticipated, the DNS look has already taken place, thus reducing latency.
DNS prefetching can be added to a specific URL by adding the rel=”dns-prefetch” tag to the link attribute. For example:
Mozilla’s MDN web docs DNS prefetch entry explains that:
“DNS requests are very small in terms of bandwidth, but latency can be quite high, especially on mobile networks. By speculatively prefetching DNS results, latency can be reduced significantly at certain times, such as when the user clicks the link. In some cases, latency can be reduced by a second.”
Prerendering steps things up a notch, letting you tell the browser to download entire pages.
Let’s say, for example, you absolutely know for sure (because you checked your analytics and it’s a common usage pattern) that users will land on your homepage and then proceed to visit services.html because this is the most popular navigation. You can give the browser a resource hint:
After downloading the homepage, the browser will then download services.html in the background and have it ready for the user as soon as they ask for it. When they finally click the “Services” link, the prerendered page will load instantaneously.
But what if the user doesn’t click to visit your “Services” page and instead navigates to the “About” page? Needless to say, prerendering is a risky technique because you’re gambling on a user’s next move.
If you’re right, you’ll save the time of downloading a whole other page. But if you’re wrong, it can cause major bandwidth waste, which is especially detrimental to mobile users.
Third-party resources can really slow a page down thanks in no small part to the number of round-trips needed before the browser can actually start downloading the resource. These round-trips include DNS lookup, TCP handshake, and TLS negotiation for HTTPS.
Depending on the page and the network conditions, these round-trips can add hundreds of milliseconds of latency or more, which can add up quickly if you’re requesting resources from several different hosts. For example, your page might connect to Twitter and Facebook for social sharing, Gravatar for comments, and Google Analytics.
But what if you could eliminate some of these round-trips and speed up perceived performance and actual loading time?
Preconnect lets you tell the browser that your page intends to establish a connection to an external resource, and that you’d like the process to start ASAP. Here’s an example of how you would use this resource hint:
<link rel=”preconnect” href=”https://example.com”>
Say you wanted to speed up the display of Google Fonts webfonts on your page. The service is reliable and generally fast due to Google’s global CDN. But since @font-face rules must first be discovered in CSS files before the browser makes webfont requests, there can be a noticeable flash of unstyled content (FOUC) during page render.
With preconnect, you can greatly reduce this delay by adding the following preconnect hint:
As Viget senior front-end developer Jeremy Frank writes in his guide to preconnect hints, adding preconnect removed 3 round-trips from the critical rendering path in his testing and cut more than half a second of latency:
What’s great about this particular example is that using preconnect helps to reduce rendering blocking and improves time to paint.
According to Google web performance engineer Ilya Grigorik:
“Preconnect is an important tool in your optimization toolbox… it can eliminate many costly round-trips from your request path—in some cases reducing the request latency by hundreds and even thousands of milliseconds.”
Prebrowsing techniques have been around for some years now and are more prevalent across the web than you may realize—Google uses resource hints to make search almost instantaneous for its users.
Ready to get started with prebrowsing on your site? Think about what you know about your pages and your users; start noting down user patterns, dig into your Google Analytics to find out how users navigate your site and what resources they use. Armed with this information, you can speed up and improve the user experience.