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:
, 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.
Much like the DNS prefetch method, preconnect will resolve the DNS but it will also make the TCP handshake, and optional TLS negotiation. It can be used like this:
<link rel="preconnect" href="https://css-tricks.com">
For more information, Ilya Grigorik wrote a great post about this handy resource hint:
Modern browsers try their best to anticipate what connections the site will need before the actual request is made. By initiating early “preconnects”, the browser can set up the necessary sockets ahead of time and eliminate the costly DNS, TCP, and TLS roundtrips from the critical path of the actual request. That said, as smart as modern browsers are, they cannot reliably predict all the preconnect targets for each and every website.
The good news is that we can — finally — help the browser; we can tell the browser which sockets we will need ahead of initiating the actual requests via the new preconnect hint shipping in Firefox 39 and Chrome 46!
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.
Subresources (see note)
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="https://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.
Finally some quick and recent documentation on this. Thank you!
Fact is some time ago I asked about something like this but with “improper” terms I think.
Simply put, lets say I have a “loading…” image in my site, along maybe with a background tile image, nothing fancy.
Is there a way to tell “hey download these things in the 6 top spots of parallel requests“?
Great Article Robin. Thank you.
<link rel="subresource"…isn’t as useful as you might think…
In Chrome subresources hinted this way get a really low download priority by default (https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp&q=LinkSubresource&sq=package:chromium&type=cs&l=122)
When the browser discovers them by normal means then they should get re-prioritised appropriately.
When preload is fully supported then the need for
rel=subresourceshould hopefully go away.
subresourceare really great. I would prefer to implement only them just because, I assume, they won’t make me think too much.
I really love this! I been looking for something else to help boost site performance.
Most of use have probably heard of these attributes before. The problem is adoption and if we can use them or not. A detailed list of if they are usable in each browser would be key to this article. Thanks for writing it!
The following table provides browser support information
Most of us have probably heard of http://caniuse.com Ben. lol
LOL exactly my point! This stuff is barely supported. Anyone who pays attention the spec updates ihavenolife knows that these exist. Its the support that’s the gotcha’s.
Had no idea about most of these, this is great. I’m guessing that if
prerenderis used the server must return a 304 when the link is clicked? Or does it not check with the server at all?
You didn’t mention
preconnect, which is available in Chrome 46 and Firefox 39 – https://www.igvita.com/2015/08/17/eliminating-roundtrips-with-preconnect/
Thanks, Joseph! I’ve just updated the post with that resource hint.
I noticed the DNS prefetch is protocol relative (
//example.com). Is there a specific reason for that, keeping this in mind?
So here we go, on the one hand I learned here that we can use HTML declarations for pre-this and pre-that however on the other hand I would say its still considered that we continue using script.
The apparent fact that the browser makes arbitrary decisions when HTML pre-processing is used makes sense. It also makes sense that there is some type of contract between the browser and script however it is my understanding the browser remains the arbiter and the script simply issuing requests via the browsers scripting engine which exposes its APIs to script.
I’ve implemented using only the HTML and saw immediate results in modern browsers. If my understandings are correct and I (we) remain encouraged to also use script how is the precedence managed and by what?
The browser remains the arbiter but which of its twin children are favored and what could possibly happen when the browser gets pre-processing commands that may be contradictions. W3C doesn’t tell us much about the difference when using Link types.
This is amazing. Thanks for sharing.
These are great, but what’s the impact on things like Google Analytics & prerender? does that count as a hit?