Teaches resource preloading to prioritize critical assets. Use when critical resources like fonts, hero images, or key scripts are discovered late in the loading waterfall.
Preload (<link rel="preload">) is a browser optimization that allows critical resources (that may be discovered late) to be requested earlier. If you are comfortable thinking about how to manually order the loading of your key resources, it can have a positive impact on loading performance and metrics in the . That said, preload is not a panacea and requires an awareness of some trade-offs.
<script> tags in <head>)<link rel="preload"> for resources needed immediately on the current pageas attribute to specify the resource type (script, style, font, image)crossorigin on the preload to match the eventual request mode<link rel="preload" href="emoji-picker.js" as="script">
...
</head>
<body>
...
<script src="stickers.js" defer></script>
<script src="video-sharing.js" defer></script>
<script src="emoji-picker.js" defer></script>
When optimizing for metrics like Time To Interactive or First Input Delay, preload can be useful to load JavaScript bundles (or chunks) that are necessary for interactivity. Keep in mind that great care is needed when using preload as you want to avoid improving interactivity at the cost of delaying resources (like hero images or fonts) necessary for First Contentful Paint or Largest Contentful Paint.
If you are trying to optimize the loading of first-party JavaScript, you can also consider using <script defer> in the document <head> vs. <body> to help with early discover of these resources.
While prefetching is a great way to cache resources that may be requested some time soon, we can preload resources that need to be used instantly. Maybe it's a certain font that is used on the initial render, or certain images that the user sees right away.
Say our EmojiPicker component should be visible instantly on the initial render. Although it should not be included in the main bundle, it should get loaded in parallel. Just like prefetch, we can add a magic comment in order to let webpack know that this module should be preloaded.
const EmojiPicker = import(/* webpackPreload: true */ './EmojiPicker')
Webpack 4.6.0+ allows preloading of resources by adding
/* webpackPreload: true */to the import. In order to make preloading work in older versions of webpack, you'll need to add thepreload-webpack-pluginto your webpack config.
After building the application, we can see that the EmojiPicker will be preloaded.
Asset Size Chunks Chunk Names
emoji-picker.bundle.js 1.49 KiB emoji-picker [emitted] emoji-picker
vendors~emoji-picker.bundle.js 171 KiB vendors~emoji-picker [emitted] vendors~emoji-picker
main.bundle.js 1.34 MiB main [emitted] main
Entrypoint main = main.bundle.js
(preload: vendors~emoji-picker.bundle.js emoji-picker.bundle.js)
The actual output is visible as a link tag with rel="preload" in the head of our document.
<link rel="preload" href="emoji-picker.bundle.js" as="script" />
<link rel="preload" href="vendors~emoji-picker.bundle.js" as="script" />
The preloaded EmojiPicker could be loaded in parallel with the initial bundle. Unlike prefetch, where the browser still had a say in whether it thinks it's got a good enough internet connection and bandwidth to actually prefetch the resource, a preloaded resource will get preloaded no matter what.
Instead of having to wait until the EmojiPicker gets loaded after the initial render, the resource will be available to us instantly! As we're loading assets with smarter ordering, the initial loading time may increase significantly depending on your users device and internet connection. Only preload the resources that have to be visible ~1 second after the initial render.
async hackShould you wish for browsers to download a script as high-priority, but not block the parser waiting for a script, you can take advantage of the preload + async hack below. The download of other resources may be delayed by the preload in this case, but this is a trade-off a developer has to make:
<link rel="preload" href="emoji-picker.js" as="script">
<script src="emoji-picker.js" async>
crossoriginFonts are fetched as CORS resources, even when they are self-hosted on the same origin. This means the preload request and the eventual @font-face request need to use the same fetch mode, or the preload cannot be reused.
If you preload a font without crossorigin, the browser will typically make a no-cors preload request and later a separate cors request when CSS discovers the font. That leads to a double fetch of the same file and wastes bandwidth.
Avoid:
<link
rel="preload"
href="/fonts/inter-roman.woff2"
as="font"
type="font/woff2" />
Prefer:
<link
rel="preload"
href="/fonts/inter-roman.woff2"
as="font"
type="font/woff2"
crossorigin />
And make sure the @font-face matches the same resource:
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-roman.woff2') format('woff2');
font-display: swap;
}
This same rule applies more broadly: if the eventual consumer fetches a resource with CORS semantics, the preload should match that mode too.
Thanks to some fixes to preload's queue-jumping behavior in Chrome 95+, the feature is slightly safer to use more broadly. Pat Meenan of Chrome's new recommendations for preload suggest:
Again, use preload sparingly and measure its impact in production. If the preload for your image is earlier in the document than it is, this can help browsers discover it (and order relative to other resources). When used incorrectly, preloading can cause your image to delay First Contentful Paint (e.g CSS, Fonts) - the opposite of what you want. Also note that for such reprioritization efforts to be effective, it also depends on servers prioritizing requests correctly.
You may also find <link rel="preload"> to be helpful for cases where you need to fetch scripts without executing them.
A variety of web.dev articles touch on how to use Preload to: