Common problems with rel="preload"
<link> tags are a type of browser resource hint, telling the browser to start downloading a file with a high priority.
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.
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
asvalue and it is preloaded intentionally.
There are a few common causes of this:
preload(high-priority) when you meant
- removing a resource from a page, but not removing the corresponding
- preloading resources loaded by a third-party script, but then the third-party stops using that resource
Deprioritizing important resources
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.
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 you look at the request waterfall you can see that the font is actually loaded twice.
(Using a DebugBear waterfall here, as WebPageTest seems to not show the second request. DevTools also shows it correctly though.)
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.
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.