Preload late-discovered Hero images faster
August 8, 2020
Preload allows you to inform the browser about critical resources you want to load as soon as possible, prior to them being found in HTML. If you are optimizing Largest Contentful Paint (LCP), preload can be a game-changer for boosting download priority of late-discovered Hero images and resources, loaded via JavaScript.
<link rel="preload" as="image" href="hero-image.jpg">
Preload can substantially improve LCP, especially if you need critical images (like Hero images) to be prioritized over the loading of other images on a page. While browsers will try their best to prioritize the loading of images in the visible viewport, <link rel=preload>
can offer a significant boost in priority.
If you currently have:
- Hero images that rely on JavaScript to load them
- A React, Vue or Angular component loading
<img>
tags client-side - Client-side rendered HTML responsible for loading images
- A React, Vue or Angular component loading
- Background hero images in CSS. These are discovered really late.
- Hero images that rely on JavaScript + a network fetch to load
- e.g require a JSON fetch from an API to discover images
- Use a webpack-loader to load in images
Preload may be able to speed up image display substantially. The key idea here is that you want to avoid the browser having to wait for the script before beginnning to load the image, as this could heavily delay when users can actually see it.
I use <link rel=preload>
in many of my single-page apps to optimize Core Web Vitals; specifically how soon the primary imagery visible in the viewport loads.
Above is a WebPageTest film-strip from loading a React-based movie browser. The app uses client-side rendering (app.js) and also relies on a fetch to an API to return a JSON feed of images (movies.json). This means the browser may need to process app.js, before it starts fetching movies.json and can discover our hero image (poster.jpg).
Using preload on the hero image, Largest Contentful Paint (the orange frame) is 1 second faster on 4G. This improves user-perceived performance as less time is spent waiting for meaningful content to appear in the viewport.
Preload late-discovered resources
<link rel=preload>
can be used in a few different ways to optimize the loading of late-discovered images.
Preload a hero-image so it's discovered before the time JS outputs an <img>
<link rel="preload" as="image" href="poster.jpg">
Now that browser support for WebP has improved, you might also like to know that WebP images can also be preloaded:
<link rel="preload" as="image" href="poster.webp" type="image/webp">
Preload a responsive image so the correct source is discovered sooner
<link rel="preload" as="image"
href="poster.jpg"
imagesrcset="
poster_400px.jpg 400w,
poster_800px.jpg 800w,
poster_1600px.jpg 1600w"
imagesizes="50vw">
Preload the JSON as fetch so it's discovered before JS gets to request it
<link rel="preload" as="fetch" href="movies.json">
In my case, movies.json requires a cross-origin fetch, which you can get working with preload if you set the crossorigin
attribute on the link
element:
<link rel="preload" as="fetch" href="foo.com/api/movies.json" crossorigin>
For bonus points, you can also preconnect to the origin this fetch is going to connect to:
<link rel="preconnect" href="https://foo.com/" crossorigin>
Preload the JS to shorten the time it takes to discover from HTML
<link rel="preload" as="fetch" href="app.js">
Wrapping up
Preload helps ensure critical hero images and resources get shown to users as soon as possible. To discover if there are opportunities preload could make a difference to your app, try out Lighthouse or PageSpeed Insights, which have an audit for preloads.