Preload <link>
tags are a type of browser resource hint. They tell the browser to start downloading a file before they would have been discovered otherwise.
You can use preload tags to make your site load faster, but when used incorrectly they can also slow it down. This article highlights common mistakes when using preload hints, and explains how to avoid them.
How to use preload correctly
First, let's look at how preload is supposed to work.
This WebPageTest waterfall shows a common performance problem that can be solved using preload. A CSS file references a font, but this font doesn't start loading until the CSS file has been fetched.
By adding a preload tag to the document, the browser can start loading the font and the CSS file at the same time. You can see this on the Shopify homepage, where the fonts are preloaded to make sure the page quickly renders with the correct fonts.
Preloading too many resources
Preload tags can help the browser prioritize important requests. But preloading a lot of files can actually make the prioritization worse, the your page will load more slowly.
Take a look at this example from the Asana homepage. The green line in the request waterfall shows when the page starts rendering.
It looks like all of these JavaScript files are render-blocking. But actually, the page contains 26 preload tags.
Instead of loading the important render-blocking resources, Chrome focusses on a large number of low-priority files.
Preloading unused resources
If a preloaded file isn't used Chrome will show a message like this:
The resource https://fonts.googleapis.com/css2?family=Ranchers was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate
as
value and it is preloaded intentionally.
There are a few common causes of this:
- using
preload
(high-priority) when you meantprefetch
(low-priority) - removing a resource from a page, but not removing the corresponding
preload
tag - preloading resources loaded by a third-party script, but then the third-party stops using that resource
Deprioritizing important resources
This waterfall shows a site with a large render-blocking CSS file and a preloaded JavaScript file that's used later on (angular.js
).
The preload is competing with the render-blocking file for bandwidth. As a result, the download takes longer and the page renders more slowly.
The page renders 0.9s faster without the preload.
The downside of this change is that the JavaScript file will now finish loading later. Depending on the relative importance of the initial render compared to the full app load this may be fine, or you might actually want to intentionally prevent rendering until the app code has loaded.
One simple way to speed up this example is using a preconnect tag. This makes sure that the browser establishes a server connection, but does not start consuming bandwidth downloading the resource.
If the app code is important, but less important than the initial render, consider lazy-loading other content like images. That way bandwidth will first be used to load the render-blocking CSS file, then to load the app code, and finally to load the images.
CORS mode mismatch
Preload can prioritize resource loading by starting requests early, but this only works if the subsequent browser request matches the preload request. (Thanks to Jakub for bringing up this issue on Twitter.)
This is especially common with fonts, which are always loaded using anonymous mode CORS.
Let's say this is your preload tag:
<link
rel="preload"
href="https://fonts.gstatic.com/s/ranchers/v8/zrfm0H3Lx-P2Xvs2ArDfBi_fXiHu.woff2"
as="font"
/>
If we run a speed test and look at the request waterfall we can see that the font is actually loaded twice.
(In this case it's then served from the browser cache. This behavior seems inconsistent and might be a Chrome bug.)
The console will show a warning like this:
A preload for 'https://fonts.gstatic.com/s/ranchers/v8/zrfm0H3Lx-P2Xvs2ArDfBi_fXiHu.woff2' is found, but is not used because the request credentials mode does not match. Consider taking a look at crossorigin attribute.
Adding the crossorigin
attribute to the link
tag ensures that both requests are made using CORS headers. The preload response can then be safely reused for the actual font load.
Using low-priority requests to preload images
Preload requests generally have the same priority as a request that fetches the resource directly. For images that means the request priority is low.
However, when preloading the image that's responsible for the Largest Contentful Paint you want the browser to prioritize the image request.
You can use priority hints and the fetchpriority
attribute to tell the browser that this image is important.
<link rel="preload" href="/images/photo.jpg" as="image" fetchpriority="high" />
How to check if browser resource hints are working correctly
We've built a free resource hint validator that automatically tests your page for common problems.
Monitor site speed and Core Web Vitals
DebugBear keeps track of your website speed over time and provides an in-depth analysis that you can use to make it faster.
Each test result shows you what resources are preloaded and what the priority of the request is.