Web App Optimization: Optimizing Images with Cloudinary
Images make up a large portion of the overall web traffic. On Instagram alone, over 95 million photos are shared daily. Delivery images in a fast and efficient way can improve the overall performance of a web application. This article covers some techniques that can be used with Cloudinary to make this seamless.
What is Cloudinary?
Cloudinary is a SaaS technology company that provides cloud-based media management services to its users. Using Cloudinary, users can upload, store, manage and manipulate media assets in a variety of ways. To start using Cloudinary, you have to create an account. You can create an account for free. Once done, you are taken to your dashboard.
Navigate to the Media Library tab to upload an image or video. You’ll find a bright orange button that you can use.
Once uploaded, you can hover on the image or video to get the URL and use in your web application.
Use the Right Image Format
There are various image formats: SVG, PNG, JPG being some of the popular formats. Each of these formats has it’s strengths and weaknesses. As a general rule, use:
- Vector images for simple shapes (logos, icons, texts)
- Raster images for complex scenes (photos)
There are also newer formats like WebP, JPEG-XR, with better encoding but are only supported in newer browsers. This makes it challenging choosing which format to send to the browser. You can take advantage of Cloudinary’s fetch (f_
) transformation to choose a specify the format you want.
Say I want to send a png image, I can use it like so:
https://res.cloudinary.com/codehacks/image/upload/f_png/v1580984200/demo.jpg
Even though the original image is a JPEG, the image delivered to the browser is in PNG format. But we may want to take advantage of newer image formats like WebP while making sure older browsers can still get a suitable format. We can use the f_auto and Cloudinary will automatically determine a suitable format to send to the browser-based on the browser’s capabilities.
https://res.cloudinary.com/codehacks/image/upload/f_auto/v1580984200/demo.jpg
You can check the official guide to see what’s possible.
Lazy loading
Lazy loading is a technique that involves loading images only when they are needed i.e. currently in the user’s visible region. In a previous article, I covered this technique extensively. It covers techniques on lazy loading, error handling, and graceful fallback mechanisms when all fails.
Serve Scaled Images
One technique that can be used to optimize your images is to serve an appropriately sized image. Most times we end up sending down more pixels than the browser needs to display.
As can be seen from the picture above, the intrinsic size (actual size) of the image is 1050×700 pixels but setting the width to 400 pixels has forced the browser to rescale the image the fit the specified size. Not only are we sending down unnecessary bytes to the user, but the browser is also forced to use more CPU resources than required which takes a hit on performance.
Use srcset and sizes attribute
One way to improve this is by using srcset
and sizes
attributes. This can be achieved like so:
<img
srcset="images/demo-400.jpeg 400w,
images/demo-750.jpeg 750w"
sizes="(max-width: 600px) 400px,
750px"
src="images/demo-750.jpeg"
alt="Room with rays of the sun coming in through the windows">
srcset
allows you to define a set of images the browser can choose between and the intrinsic width of each image. In the example above,
srcset=”images/demo-400.jpeg 400w”
Tells the browser the path of the image (images/demo-400.jpeg), followed by a space and then the intrinsic width of the image. Each image is separated by a comma.
sizes
contain a media condition (max-width: 600px) and an intended display size (400px) of the image. It’s also a comma-separated list. The second item, in this case, doesn’t have a media condition so it defaults to anything above 600px.
Older browsers that don’t support these attributes will ignore them and use the src
attribute.
Using Cloudinary
Using the solution above, we would have to create multiple sized images for every image which can be a chore. We can upload our image to Cloudinary and resize it on the fly using adding width (w_
) and height (h_
) transformations. After uploading the image to Cloudinary, the link is:
https://res.cloudinary.com/codehacks/image/upload/v1580984200/demo.jpg
We can specify the width and height on the fly like so:
https://res.cloudinary.com/codehacks/image/upload/w_750,h_400,c_scale/v1580984200/demo.jpg
Rewriting the previous code:
<img
srcset="https://res.cloudinary.com/codehacks/image/upload/w_400/v1580984200/demo.jpg 400w,
https://res.cloudinary.com/codehacks/image/upload/w_750/v1580984200/demo.jpg 750w" sizes="(max-width: 600px) 400px,
750px"
src="https://res.cloudinary.com/codehacks/image/upload/w_750/v1580984200/demo.jpg"
alt="Room with rays of the sun coming in through the windows">
It’s easier to specify even more sources and sizes using this combination. In this case, we scale (c_scale
) the image but Cloudinary also provides support to fill, fit, crop, thumbnail and more with our images. Use this guide to find out more.
Remove Unnecessary Image Metadata
One of the things that add to the overall image size is metadata. For reference sake, here is an example:
This data, in most cases, is not used. Why send them to the browser then? When images are uploaded to Cloudinary, they are kept as-is. If a transformation (cropping, scaling, etc) is applied when fetching the image, image metadata gets stripped. You can still keep metadata on transformation by using the keep_iptc flag.
https://res.cloudinary.com/codehacks/image/upload/fl_keep_iptc,w_750,c_scale/v1580984200/demo.jpg
Compress Image Assets
You can optimize your web app performance by compressing your images. This reduces the quality of your images which in turn, reduces the size of images. The effect is that images load faster.
Using Cloudinary, it’s quite trivial to compress images while still maintaining the quality. You can do so using the quality transformation (q_
):
https://res.cloudinary.com/codehacks/image/upload/q_60/v1580984200/demo.jpg
This reduces the image size from 96.6kb to 39.4kb. Huge savings already. You can also allow Cloudinary to automatically determine the quality compression level using q_auto
.
https://res.cloudinary.com/codehacks/image/upload/q_auto/v1580984200/demo.jpg
This reduces the image size from 96.6kb to 52.4kb. You make this even more aggressive with q_auto:best
, :good,
:eco
, or :low
.
https://res.cloudinary.com/codehacks/image/upload/q_auto:eco/v1580984200/demo.jpg
Which takes the image down to 48.8kb.
Conclusion
Images make up a large percentage of the bytes transferred over the web everyday. Delivering images efficiently requires some techniques that can be achieved easily using Cloudinary. The example transformations used can be found here.