When we talk about front end performance we think things like concatenation, minification, caching, or gzipping assets on the server so that the page loads faster and users can complete their goals as quickly as possible.
Resource prefetching is another performance enhancing technique. We can use it to tell the browser which assets the user might need in the future—before they even need them.
Pre-fetching is a way of hinting to the browser about resources that are definitely going to or might be used in the future, some hints apply to the current page, others to possible future pages.
As developers, we know our applications better than the browser does. We can use this information to inform the browser about core resources.
This practice of guessing what users need before they need it is has been called prebrowsing. It’s not just a single technique though, it breaks down into a number of different techniques:
subresource, the standard
This notifies the client that there are assets we’ll need later from a specific URL so the browser can resolve the DNS as quickly as possible. Say we need a resource, like an image or an audio file, from the URL `example.com`. In the
<head> of the document we’d write:
<link rel="dns-prefetch" href="//example.com">
Then, when we request a file from it, we’ll no longer have to wait for the DNS lookup. This is particularly useful if we’re using code from third parties or resources from social networks where we might be loading a widget from a
In his epic front-end performance post, Harry Roberts suggests using this technique:
That simple line will tell supportive browsers to start prefetching the DNS for that domain a fraction before it’s actually needed. This means that the DNS lookup process will already be underway by the time the browser hits the script element that actually requests the widget. It just gives the browser a small head start.
This might seem like such a tiny performance improvement as to not matter very much, but this is not necessarily the case – Chrome does something similar all the time. It’ll automatically preresolve the DNS (and sometimes even prerender the page) if you type just a small part of the domain into the URL bar, thus shaving crucial milliseconds off each request.
If we’re certain that a specific resource will be required in the future, then we can ask the browser to request that item and store it in the cache for reference later. For example an image or a script, or really anything that’s cacheable by the browser:
<link rel="prefetch" href="image.png">
Unlike DNS prefetching, we’re actually requesting and downloading that asset and storing it in the cache. However, this is dependent on a number of conditions, as prefetching can be ignored by the browser. For example, a client might abandon the request of a large font file on a slow network. Firefox will only prefetch resources when “the browser is idle”.
As Bram Stein explains in his post on the matter, this could have huge performance benefits for webfonts. At the moment, font files have to wait for the DOM and CSSOM to be constructed before they even download. But, if we prefetch them, then that bottleneck can be circumnavigated with ease.
Note: although prefetching assets used to be a little difficult to test, Chrome and Firefox will now show prefetched resources in the Network panel. Also, it’s helpful to remember that there’s no same-origin restriction for link prefetching.
Another prefetching technique helps identify the resources that are the highest priority and should be requested before prefetched items. For example, in Chrome and Opera we could add the following to the
head of our document:
<link rel="subresource" href="styles.css">
According to the Chromium docs, it works like this:
“LINK rel=subresource” provides a new link relation type with different semantics from LINK rel=prefetch. While rel=prefetch provides a low-priority download of resources to be used on subsequent pages, rel=subresource enables early loading of resources within the current page.
So: if the asset is required for the current page, or if it’s needed as soon as possible, then it’s probably best to use
subresource, otherwise stick to
This is the nuclear option, as
prerender gives us the ability to preemptively load all of the assets of a certain document, like so:
<link rel="prerender" href="http://css-tricks.com">
Steve Souders wrote a great explanation about this technique:
href, then the hidden page is swapped into view making it appear to load instantly. Google Search has had this feature for years under the name Instant Pages. Microsoft recently announced they’re going to similarly use prerender in Bing on IE11.
But beware! You should probably be certain that the user will click that link, otherwise the client will download all of the assets necessary to render the page for no reason at all.
As with any of this anticipatory work, there’s a risk that the prediction is wrong. If the anticipatory work is expensive (e.g., steals CPU from other processes, consumes battery, or wastes bandwidth) then caution is warranted. It would seem difficult to anticipate which page users will go to next, but high confidence scenarios do exist:
- If the user has done a search with an obvious result, that result page is likely to be loaded next.
- If the user navigated to a login page, the logged-in page is probably coming next.
- If the user is reading a multi-page article or paginated set of results, the page after the current page is likely to be next.
Finally, the Page Visibility API can be used to guard against scripts firing before they’re rendered on the user’s screen.
OK, so with those design considerations out of the way, we can talk about future additions to the spec that might be of interest, too.
Future option: Preloading
A new spec called preload suggests that sometimes it’s best to always download an asset, regardless of whether the browser thinks that’s a good idea or not. Unlike prefetching assets, which can be ignored, preloading assets must be requested by the browser.
<link rel="preload" href="image.png">
So, although preloading is not currently supported by any browser at the moment, the idea behind it is certainly interesting.
Predicting what our users will do next is difficult, and it certainly requires a lot of planning and testing. But, the performance benefits are definitely worth chasing. If we’re willing to experiment with these prefetching techniques, then we’re sure to improve the user experience in a noticeable way.
More information about prefetching, preloading, prebrowsing techniques
- Slides from a talk by Ilya Grigorik called Preconnect, prerender, prefetch
- MDN link prefetching FAQ
- W3C preload spec
- Harry Roberts on DNS prefetching
- HTML5 prefetch
- Preload hints for webfonts