Loading...
These are mad times we live in, mad! There is an insatiable demand for a silky smooth user experience, instantaneous loading times, and unlimited content.
When thinking about load times, one thing that comes to mind is images. Have you ever experienced the frustration of being on a loaded webpage, only to have to wait for images to load on further interaction with the page. Of course you have. If you are developing a website with many images you will undoubtedly want to spare your users from this vexation.
Luckily, there is a simple way to go about this if:
- You have the image URLs ahead of time
- You can accurately predict which images the user will likely see next
If the above isn't true then this article may not be super useful to you.
Basic Prefetching
const urls = [
"shorturl.at/auLWY",
"shorturl.at/sBTX5"
];
urls.forEach(imageUrl => {
const imageElement = new Image(); // Create new image element
imageElement.onload = () => {}; // Do something on success
imageElement.onerror = () => {}; // Do something on error
imageElement.src = imageUrl; // Set the image URL which will trigger a network request
};
Let's talk about why the approach above actually works.
The Image
constructor, which is functionally equivalent to document.createElement('img')
, creates a new image instance. The purpose of creating these images is not for display, but rather to set the image src
attribute which in turn will trigger a network request for the image. If you can accurately predict which images the user is likely to see next based on some logical flow of interaction, then you can ensure the images have already been delivered to the browser by the time the user gets there.
This may seem trivial, but for large scale applications it can save a significant amount of time. In order for this to work effectively, you will need to find a practical place to prefetch in your current environment: before the user sees the images and after any heavy initialization tasks as to not affect your web application's initial load time.
Prefetching w/Promises
const urls = [
"shorturl.at/auLWY",
"shorturl.at/sBTX5"
];
Promise.all(urls.map(imageUrl => {
return new Promise((resolve, reject) => {
const imageElement = new Image(); // Create new image element
imageElement.onload = () => { resolve(); }; // Do something on success
imageElement.onerror = () => { reject(); }; // Do something on error
imageElement.src = imageUrl; // Set the image URL which will trigger a network request
};
}))
.then(() => {}) // Do something after all images load
.catch((err)=> {}); // Do something if there are any errors
Additionally, if find it necessary to have more control over the loading state of your images, such as triggering some function when they all load successfully or to conditionally display some skeleton component, there is an easy way to do so using promises.
Simply map each image url to a new promise and resolve/reject the promise as it suits your needs. Wrap the promise array in a Promise.all
and use the then
and catch
methods to execute the appropriate action. That's it!
I hope this article has helped you understand how you can use prefetching to improve your web application's user experience. Let me know in the comments if it works for you!
Top comments (1)
This isn't prefetching, this is lazy loading and I think many browsers support a built in property for this.