Pre-Loading and Pre-Decoding Images with Javascript for Better Performance

javascript
Published on January 31, 2019

The Background

Pre-loading an image is a popular technique to ensure that the user does not see a delay while he is performing an action involving the image.

For example, you are sure that the user is going to see an image in the next few seconds or so. To give the user the best experience :

  1. the application pre-loads the image with Javascript
  2. user comes to the section that holds the image
  3. user sees the image without any delay

Your typical Javascript code will look something like this :

var img = new Image();
img.src = "sample-image.jpg";
img.onload = function() {
	document.querySelector("#container").appendChild(img);
};
img.onerror = function() {
	console.log('Image loading failed');
};

You may think that you have covered all bases. But interestingly, there is more you could have done.

Process of Showing an Image in the Browser

An image is shown in the browser in a series of steps :

  1. The browsers loads the image from the server
  2. Then the browser starts to read the image data — known as decoding
  3. Then from the decoded data, image pixels are painted on the screen. This is what you finally see.

With performance in mind, you can load the image asynchronously in the background so that your application running on the main thread is not affected.

But when it comes to decoding, there is a catch. They are being decoded in the main thread, synchronously. For small images you may probably not feel the difference. But for heavy images, say HD or UHD, it takes quite a bit of time to decode an image — the user interface will be frozen during that time.

Till now there was nothing you could have done in your Javascript code to handle decoding. But now, browsers are giving an option to handle the decoding phase by yourself.

Handling Image Decoding with decode

The decode is a newly added method that you can apply it to an Image object. This method will load, and then decode the image. Both are done in parallel, and does not affect the execution on the main thread.

The return value of decode is a Promise. When the image decoding is finished successfully, this Promise will be resolved. In case of any image loading error, or decoding error the Promise will fail.

With the decode method, your code will look like :

var img = new Image();
img.src = "sample-image.jpg";
img.decode().then(function() {
	document.querySelector("#container").appendChild(img);
}).catch(function(error) {
	console.log(error.message);
});

Note that the image loading is handled by the decode function itself.

Time Validity of the Decoded Image Data

The browser will guarantee that the decoded data will be available for at least one frame. After that depending on the memory consumption, the decoded data may or may not be discarded. So it is better to consume the decoded data and show the image as soon as possible.

Any Way to Not Decode the Image ?

SVG images already come in decoded form. So browser does not have to decode a SVG image.

Browser Compatability

As of Dec 2019, all major browsers support the decode method.

To ensure browser compatibility, you can do a check for decode method.

// ensuring browser compatibility
var img = new Image();
img.src = "sample-image.jpg";

if('decode' in img) {
	img.decode().then(function() {
		document.querySelector("#container").appendChild(img);
	});
}
else {
	document.querySelector("#container").appendChild(img);
}
In this Tutorial