Resource Hints
Introduction
Over the past decade resource hints have become essential primitives that allow developers to improve page performance and therefore the user experience.
Preloading resources and having browsers apply some intelligent prioritization is something that was actually started way back in 2009 by IE8 with something called the preloader. In addition to the HTML parser, IE8 had a lightweight look-ahead preloader that scanned for tags that could initiate network requests (<script>, <link>, and <img>).
Over the following years, browser vendors did more and more of the heavy lifting, each adding their own special sauce for how to prioritize resources. But it’s important to understand that the browser alone has some limitations. As developers however, we can overcome these limits by making good use of resource hints and help decide how to prioritize resources, determining which should be fetched or preprocessed to further boost page performance.
In particular we can mention a few of the victories resource hints achieved/made in the last year:
- CSS-Tricks web fonts showing up faster on a 3G first render.
- Wix.com using resource hints got 10% improvement for FCP.
- Ironmongerydirect.co.uk used preconnect to improve product image loading by 400ms at the median and greater than 1s at the 95th percentile.
- Facebook.com used preload for faster navigation.
Let’s take a look at most predominant resource hints supported by most browsers today: dns-prefetch, preconnect, preload, prefetch, and native lazy loading.
When working with each individual hint we advise to always measure the impact before and after in the field, by using libraries like WebVitals, Perfume.js, or any other utility that supports the Web Vitals metrics.
dns-prefetch
dns-prefetch helps resolve the IP address for a given domain ahead of time. As the oldest resource hint available, it uses minimal CPU and network resources compared to preconnect, and helps the browser to avoid experiencing the “worst-case” delay for DNS resolution, which can be over 1 second.
<link rel="dns-prefetch" href="https://www.googletagmanager.com/">
Be mindful when using dns-prefetch as even if they are lightweight to do it’s easy to exhaust browser limits for the number of concurrent in-flight DNS requests allowed (Chrome still has a limit of 6).
preconnect
preconnect helps resolve the IP address and open a TCP/TLS connection for a given domain ahead of time. Similar to dns-prefetch it is used for any cross-origin domain and helps the browser to warm up any resources used during the initial page load.
<link rel="preconnect" href="https://www.googletagmanager.com/">
Be mindful when you use preconnect:
- Only warm up the most frequent and significant resources.
- Avoid warming up origins used too late in the initial load.
- Use it for no more than three origins because it can have CPU and battery cost.
Lastly, preconnect is not available for Internet Explorer or Firefox, and using dns-prefetch as a fallback is highly advised.
preload
The preload hint initiates an early request. This is useful for loading important resources that would otherwise be discovered late by the parser.
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">
Be mindful of what you are going to preload, because it can delay the download of other resources, so use it only for what is most critical to help you improve the Largest Contentful Paint (LCP). Also, when used on Chrome, it tends to over-prioritize preload resources and potentially dispatches preloads before other critical resources.
Lastly, if used in a HTTP response header, some CDN’s will also automatically turn a preload into a HTTP/2 push which can over-push cached resources.
prefetch
The prefetch hint allows us to initiate low-priority requests we expect to be used on the next navigation. The hint will download the resources and drop it into the HTTP cache for later usage. Important to notice, prefetch will not execute or otherwise process the resource, and to execute it the page will still need to call the resource by the <script> tag.
<link rel="prefetch" as="script" href="next-page.bundle.js">
There are a variety of ways to implement a resource’s prediction logic, it could be based on signals like user mouse movement, common user flows/journeys, or even based on a combination of both on top of machine learning.
Be mindful, depending on the quality of HTTP/2 prioritization of the CDN used, prefetch prioritization could either improve performance or make it slower, by over prioritizing prefetch requests and taking away important bandwidth for the initial load. Make sure to double check the CDN you are using and adapt to take into consideration some of the best practices shared in Andy Davies’s article.
Native lazy loading
The native lazy loading hint is a native browser API for deferring the load of offscreen images and iframes. By using it, assets that are not needed during the initial page load will not initiate a network request, this will reduce data consumption and improve page performance.
<img src="image.png" loading="lazy" alt="