Preload critical assets to improve loading speed

Updated
Houssein Djirdeh
Houssein Djirdeh
Milica Mihajlija
Milica Mihajlija

When you open a web page, the browser requests the HTML document from a server, parses its contents, and submits separate requests for any referenced resources. As a developer, you already know about all the resources your page needs and which of them are the most important. You can use that knowledge to request the critical resources ahead of time and speed up the loading process. This post explains how to achieve that with <link rel="preload">.

How preloading works

Preloading is best suited for resources typically discovered late by the browser.

Screenshot of Chrome DevTools Network panel.
In this example, Pacifico font is defined in the stylesheet with a @font-face rule. The browser loads the font file only after it has finished downloading and parsing the stylesheet.

By preloading a certain resource, you are telling the browser that you would like to fetch it sooner than the browser would otherwise discover it because you are certain that it is important for the current page.

Screenshot of Chrome DevTools Network panel after applying preloading.
In this example, Pacifico font is preloaded, so the download happens in parallel with the stylesheet.

The critical request chain represents the order of resources that are prioritized and fetched by the browser. Lighthouse identifies assets that are on the third level of this chain as late-discovered. You can use the Preload key requests audit to identify which resources to preload.

Lighthouse's preload key requests audit.

You can preload resources by adding a <link> tag with rel="preload" to the head of your HTML document:

<link rel="preload" as="script" href="critical.js">

The browser caches preloaded resources so they are available immediately when needed. (It doesn't execute the scripts or apply the stylesheets.)

After implementing preloading, many sites, including Shopify, Financial Times and Treebo, saw 1-second improvements in user-centric metrics such as Time to Interactive and First Contentful Paint.

Resource hints, for example, preconnectand prefetch, are executed as the browser sees fit. The preload, on the other hand, is mandatory for the browser. Modern browsers are already pretty good at prioritizing resources, that's why it's important to use preload sparingly and only preload the most critical resources.

Unused preloads trigger a Console warning in Chrome, approximately 3 seconds after the load event.

Chrome DevTools Console warning about unused preloaded resources.

preload is supported in all modern browsers except Firefox.

Use cases

Preloading resources defined in CSS

Fonts defined with @font-face rules or background images defined in CSS files aren't discovered until the browser downloads and parses those CSS files. Preloading these resources ensures they are fetched before the CSS files have downloaded.

Preloading CSS files

If you are using the critical CSS approach, you split your CSS into two parts. The critical CSS required for rendering the above-the-fold content is inlined in the <head> of the document and non-critical CSS is usually lazy-loaded with JavaScript. Waiting for JavaScript to execute before loading non-critical CSS can cause delays in rendering when users scroll, so it's a good idea to use <link rel="preload"> to initiate the download sooner.

Preloading JavaScript files

Because browsers don't execute preloaded files, preloading is useful to separate fetching from execution which can improve metrics such as Time to Interactive. Preloading works best if you split your JavaScript bundles and only preload critical chunks.

How to implement rel=preload

The simplest way to implement preload is to add a <link> tag to the <head> of the document:

<head>
<link rel="preload" as="script" href="critical.js">
</head>

Supplying the as attribute helps the browser set the priority of the prefetched resource according to its type, set the right headers, and determine whether the resource already exists in the cache. Accepted values for this attribute include: script, style, font, image, and others.

Take a look at the Chrome Resource Priorities and Scheduling document to learn more about how the browser prioritizes different types of resources.

Caution: Omitting the as attribute, or having an invalid value is equivalent to an XHR request, where the browser doesn't know what it is fetching so it can't determine the correct priority. It can also cause some resources, such as scripts, to be fetched twice.

Some types of resources, such as fonts, are loaded in anonymous mode. For those you must set the crossorigin attribute with preload:

<link rel="preload" href="ComicSans.woff2" as="font" type="font/woff2" crossorigin>

Caution: Fonts preloaded without the crossorigin attribute will be fetched twice!

<link> elements also accept a type attribute, which contains the MIME type of the linked resource. The browsers use the value of the type attribute to make sure that resources get preloaded only if their file type is supported. If a browser doesn't support the specified resource type, it will ignore the <link rel="preload">.

You can also preload any type of resource via the Link HTTP header:

Link: </css/style.css>; rel="preload"; as="style"

A benefit of specifying preload in the HTTP Header is that the browser doesn't need to parse the document to discover it, which can offer small improvements in some cases.

Preloading JavaScript modules with webpack

If you are using a module bundler that creates build files of your application, you need to check if it supports the injection of preload tags. With webpack version 4.6.0 or later, preloading is supported through the use of magic comments inside import():

import(_/* webpackPreload: true */_ "CriticalChunk")

If you are using an older version of webpack, use a third-party plugin such as preload-webpack-plugin.

Conclusion

To improve page speed, preload important resources that are discovered late by the browser. Preloading everything would be counterproductive so use preload sparingly and measure the impact in the real-world.

Last updated: Improve article

Codelabs

See it in action
Learn more and put this guide into action.