Improving Performance of Vue or Nuxt apps is not an easy task. However, there are some quick wins that you can implement easily that will drastically improve the performance of your website. One of such quick win is Image Optimization. In this talk, I will teach you how to optimize images on the fly with Digital Asset Managements services like Cloudinary or Content Management Systems, utilize the concept of Lazy Loading, use compressed format of images like WEBP, and many more!
Image Optimization - Quick Win for Improving Performance in Vue & Nuxt Apps
AI Generated Video Summary
Image optimization is crucial for website performance and user experience. Services like IPX and Cloudinary can help optimize images on the fly. Cloudinary offers additional functionalities and transformations for image management. Lazy loading and the lazy pattern can improve website performance by deferring image loading. Optimized images deliver a better user experience. Fallbacks can mitigate the impact of service failures.
1. Introduction to Image Optimization
In order to improve website performance, we often focus on the back-end. However, there are several front-end optimizations we can make. Image optimization is a quick win for improving performance and user experience. Let's start with a poll to see how many of you are using and optimizing images on your websites. Optimizing images is crucial for a well-performing website and enhances user experience. Today, we will focus on image optimization and its impact on website performance.
Okay, do you hear me well? Yeah? Good. Okay. So, you might be thinking that in order to improve performance of the website, we need to focus on the back-end stuff. Right? So, we need to optimize or make the SQL queries more efficient. We need to go for the cache implementations and stuff like that. But in reality, there are actually several things we can do on the front end itself to make it more performant. And this inspired me to basically take the topic of image optimization for today's presentation as it is, in my opinion, one of the quick wins for improving performance in your website.
So, as I've already introduced me. My name is Jakub and I work at Vue Storefront. And I'm also a Google Developer Expert in web performance. This is also one of the reasons why I selected the topic. And I'm also an ambassador in those organizations, so if you're interested in talking about any of them, just find me after the talk and we can just share the knowledge. And yeah. Talk about it. And as Dom also mentioned, we met almost two years ago on the last edition of Vue.js Live, so I'm pretty happy to be here once again. And yeah, share my knowledge with all of you.
So I will start the presentation with a little poll. So please raise your hand if you are using images in your website. That's basically really straightforward, right? It's yes, we are using the images in our websites. And now please raise your hand if you are optimizing the images. Okay. So quite a few of you, but not so many. So you can clearly see that we are all using the images, but we are not optimizing them. While optimizing images is, in my opinion, the crucial part of a well-performing website. And it's not only about the results of the Lighthouse or any other web performance auditing tool. It's also good for user experience because users want to get the data as soon as possible. Like the images, if you are looking for e-commerce website, you want to have the product image as soon as possible because you want to buy the product. So let's talk first about the image formats. So there are many technical differences between one image format and another. And in my today's talk, I wanted to focus on the optimization.
2. Importance of Image Size and Format
The size and load time of images are important factors in website performance. Formats like WebP and Avif are lighter than JPEG and PNG, but not supported by Internet Explorer. Properly sized images prevent layout shift and improve load time. Core Web Vitals, such as largest contentful paint and cumulative layout shift, rely on properly sized images. Image optimizing services can help optimize images on the fly.
So basically the size and the load time of the image. So I want to focus only on one. And yes, be prepared there will be some more memes as well.
For the users, the usual difference between one image which is, let's say, in one format and the other image, which is in different format, is usually the same. You can't see the difference. They just look the same. The only difference is the size. And this is what I will be showing during the short demo later on. But in general, formats such as WebP or Avif, I hope I pronounced it correctly, are lighter than JPEG and PNG, but they are not supported by Internet Explorer. And I'm saying this because one of my friends, until today, is supporting application that still needs to be running on Internet Explorer. So he doesn't have a great job I would say.
Yes, so we talked about the image formats. There are also cases about the size, properly sized images. And I have seen too many production websites where they were basically fetching the image, for example, for a small icon, and the image was in a full HD resolution, and then it was like squeezed into the icon that was, for example, in the footer. So this might seem like a really, really strange issue, but it happens too often, I would say, for the modern websites.
So why should we have the images in a proper size? It's basically because of the load time. If we are fetching the images in the right format, the load time will be shorter and there will be also what is the second most important thing, we won't see the layout shift. Because you will have... if you've seen some talks or articles about the web performance, you probably know already about the Core Web Vitals. This is like the metric or set of metrics that we can use in order to check how our website is performing. So there are metrics such as first, largest contentful paint and cumulative layout shift. And having the properly sized images is important for both of them. But we can optimize those images by basically replacing... or converting the one of the images format into another one. We can just have the image in correct resolution from the very beginning. But in the majority of cases, we want to be able to optimize them on the fly. By using certain software. So for that, we can use image optimizing services. I'm not sure if there is a word such as this one or a key word. I just made it up.
3. Image Optimization Services
The idea behind these services is to optimize images on the fly. IPX, developed by the Nuxt team, is a straightforward image optimizer based on Sharp and VIPS. It can be used as ExpressJS middleware or as an IPX client. It is widely used in the Nuxt ecosystem.
So basically the idea behind these services is to allow us to optimize the images on the fly. So whenever we need it, and with the parameters that we need as well. So we can use the tool called IPX, which is the tool developed by the Nuxt team as well under the NGS organization.
So IPX is the image optimizer which is based on Sharp and VIPS. And it's really straightforward, the usage of it. We can just install it and we can use it as the ExpressJS middleware or we can use it as just the IPX client. And how we can use it later on in our application? We can just send a request to the localhost with certain parameters, for example, the format. In this case, it will be webP. But the IPX works well and actually it's used in the Nuxt image, the module that is widely used in the Nuxt ecosystem for handling images.
4. Using Cloudinary for Image Management
However, there might be cases when we cannot use IPX and need a third-party service like Cloudinary. Cloudinary is a digital asset management tool that allows you to manage various types of assets on your website. It provides the flexibility to fetch assets in the desired format, size, and with optimizations. NUX image and NUX Cloudinary both integrate with Cloudinary, but NUX Cloudinary offers additional functionalities and transformations. I have collaborated with Kolby Fajok, Director of Developer Experience at Cloudinary, to release a Cloudinary module for NUX 3. Let me show you how it works. We simply install the module, register it, add the cloud name, and use the CLD image component. Cloudinary automatically selects the most efficient image format.
However, there might be cases when we basically cannot use such a thing as IPX. We just want to have third-party service handle this case for us. And for that, we can use a tool such as Cloudinary.
So Cloudinary is the digital asset management that allows you to manage your assets over the website. So photos, pictures, videos, GIFs, many things like that. And then what we can do with it is we can fetch them in a way we want. So in the right format, in the right size, with many different optimizations applied to, which I will show in a minute.
So in NUX world, we can use Cloudinary with NUX image because NUX image supports 18 providers and Cloudinary is one of them. But we can also use the Cloudinary module, which is specifically for working with Cloudinary. That was developed by Maja Chavin. Maja Chavin is also popular in the Vue community and she was the original creator of this module. And yeah, so you might be asking yourself, what is the reason or basically what is the difference between using NUX image and the NUX Cloudinary if they both can integrate with Cloudinary?
So the idea behind NUX image is to be generic. So no matter what provider you will use, you can still use it with one API for the image. However, for the NUX Cloudinary, the idea was to deliver more functionalities from Cloudinary, more optimizations, more transformations, image transformations. And there is also one more difference in the NUX Cloudinary is that it was the module itself was developed sometime ago. And it works only for NUX 2, which as you know right now, NUX is transitioning into NUX 3. So I have a small surprise for you. And I was joining forces with Kolby. Kolby Fajok is the Director of Developer Experience at Cloudinary. So we have joined forces recently to release a Cloudinary module for NUX 3. And I will show you that in a minute.
So let me just go to the code. So the usage of the Cloudinary module is really simple. We just, as with many different modules as well, we just install the module. Then we register it in the modules array. And then, basically, we just need to add the cloud name, the specific cloud name that is assigned to our account. And then what we can do is we can start using the CLD image, which is the component specifically created for working with Cloudinary. So as a result, what we have is that when we go to the local host, this is the image that is fetched from Cloudinary. And if we inspect, by the way, is the font okay? Visible? Okay. So, as you can see, the type of the image is Aviv. Because Cloudinary, by default, what the URL loader of Cloudinary will do is it will automatically try to use the most efficient image format.
5. Image Format and Size Comparison
The image size varies depending on the format used. The AVI format reduces the size to 22 kilobytes, while the original JPEG format is 33 kilobytes. PNG, on the other hand, is 200 kilobytes, significantly larger than the AVI format.
So take a look at the size. It says 22.3 kilobytes for this image. And as you can see here, the SRC of the image is JPEG, so you already see the transformation being done. It was JPEG transformed into Aviv. So let's try to make it like a WebP. So here you see 22 kilobytes. And when I refresh, you see that changing to WebP increased the size by 15 kilobytes. More or less. So let's make it an original format, which will be JPEG, if I can type it correctly. So 33 kilobytes. Now it's 55 for the original one. So we already managed to get half of the size of the image by just using this format. And now let's go for PNG just to show the difference. So with PNG, PNG is 200 kilobytes, so basically 10 times bigger than the image in the AVI format.
6. Cloudinary Functionalities and Nuxt Module
Cloudinary offers more than just format change. It allows adding overlays with text and styling to images. The upcoming version 2.0 of the Cloudinary module for Nuxt will be released next week, making it accessible to users of Nuxt free projects.
But Cloudinary doesn't only allow you to change the format. It comes with many more functionalities out of the box. So let's say that instead of just changing the format, what I would like to do here is let's add some overlay to our image, so it will have some text, some styling as well. So when I uncomment it and just make it a little bit smaller and refresh the page, you see what more can be added to the image. And this is being done fully by Cloudinary, and we can inspect that by checking the source of the image. So you see here the full source of the image. So basically, everything that we defined here in the code, the overlay, is being added as the parameters for Cloudinary to optimize the images for us. So yeah, the version 2.0 for the Cloudinary module for Nuxt is not yet released, but it will be the next week. So with the rising popularity of Nuxt free projects, you will be able to use this module in the upcoming days as well.
7. Lazy Loading of Images
Lazy loading is a pattern that involves deferring the loading of images until they are actually needed. Instead of fetching all images at the beginning, we can defer them to the point that the user will see them in the viewport.
Let me come back to the slides because I have a few more patterns that I wanted to share with you. And the first pattern that I always like to recommend and use in web applications is basically lazy loading, and specifically lazy loading of the images. So I can explain to you how it works, but I will show you a GIF with some cats that will show you basically how it works. So we have the cats, images of the cats, and you can see in the requests queue that they are fetched basically when the user is scrolling down, so when they are actually needed. So instead of fetching all of them at the beginning, at the initial load of the application, we can just defer them to the point that the user will see them in the viewport.
8. Lazy Loading and the Lazy Pattern
Lazy loading is a technique to defer loading or requesting images until they are actually needed. It is part of the lazy pattern, which involves deferring functionality until it's needed. Lazy loading can improve website performance by preventing unnecessary image requests. Additionally, there is an experimental feature called fetch priority that allows you to prioritize image loading. These techniques are just the beginning of performance optimization.
And it can be done very easily. You can use the loading attribute of the image. You can also use packages such as lozat or the intersection observer. But one small thing that I noticed recently in the Mozilla docs that lazy loading or lazy value for the loading attribute of the image is explained as that the image will be loaded when necessary. So this is not entirely exactly true, because, well, it is true, but it doesn't give you the full context of the lazy loading. Because what I noticed in many web applications like production, and I will talk about it in a second, is that there are a majority of webpages or, for example, ecommerce websites that are lazy loading the largest contentful paint.
So to give you more context, largest contentful paint should be delivered as soon as possible. And when we are using lazy loading, we are adding the request for this image to the end of the request loop, which basically makes it load longer. So here, you also see the difference in the size of the images that are running on the website that is using lazy loading and not using. Basically, as shown in the GIF with the cats, we can use it to defer loading or requesting the images until the point they are actually needed. Lazy loading is part of what I call the lazy pattern. And basically, I call it like that. I'm not sure if this is a pattern. And I'm really a big fan of this pattern. This is me with two of my cats the last lazy Sunday. So I'm a huge fan of it. And the idea behind having such a lazy pattern is to use the techniques that are related to deferring, doing some functionality until it's actually needed. This is like, I made this definition. So you can read about this lazy pattern in my DEVTOOL, in my article about improving performance of NAX with lazy pattern. And as a part of this lazy pattern, what it comes with is, of course, the lazy loading, as I mentioned. Components dynamic lazy imports, lazy data fetching composables, and lazy hydration as well. This configuration is a great package by Harlan, who is also a core team member of NAX, so you should check that out.
What's next? There's also a fetch priority, which is an experimental feature that allows you to instruct the browser when it should fetch the request. So you can basically use it to tell the browser, OK, this one is super needed, and it should be loaded as soon as possible. And we can do it very easily with the image tag. Just set fetch priority to high for the images that we want to fetch as soon as possible. And we can also instruct the browser for certain images to be fetched later on. So this is just the tip of the iceberg in improving performance. Because there is a lot of things that we should take a look at.
9. Importance of Optimized Images
By using optimized images, you deliver a better experience to users, making them feel cool. Thank you for being here and listening to me. If you'd like to find me on the Internet, search for Jakub Andrewski. I'm Barosz on GitHub. Thanks.
Because there is a lot of things that we should take a look at. And I'm sure right after me will be Filip who will be showing you some insights into web performance as well. And if you are interested more in learning more about this topic, so I have this series on DevTool about NAX performance, so NAX specific. And also recently I started writing about the web performance. So the usage of IPX which I mentioned previously, the web performance checklist, so things you should take a look at while trying to make your website more performant.
And I have a small final request to you to end my talk. By using optimized images you basically deliver a better experience to the users. This is cool. Because users like to be entertained, they like to get the cool experience. So who doesn't want to be cool, right? Okay, thank you very much for being here and listening to me. If you'd like to find me somewhere on the Internet, you can search for Jakub Andrewski. It's easier to pronounce my last name in this way than the original one. With a small difference in GitHub, I'm Barosz. Thanks. Thanks. I love your ideas about web performance. Feel free.
10. Image Loading Techniques and SVG Optimization
In a project, we had two different images as assets, loading the first one and replacing it with a better quality larger one. This technique is part of progressive loading, where you show something to the user as soon as possible, like a placeholder or loader, and then replace it with the actual image. Another idea is to display an array of plain images and replace it with the actual slider when the page loads. When it comes to optimizing SVGs, there are packages like SVGO that remove blank spaces and optimize the file. Cloudinary works with Vue and there are plans to integrate it with Vue too.
11. Vue 3 Refactoring and User-Uploaded Images
For Vue 3, we plan to refactor the module for Next into a Vue plugin. Considerations for optimizing user-uploaded images include decreasing quality, changing format, and optimizing sizes. Cloudinary has a free tier with limitations, such as no background removal. There is an open source alternative called IPX that can be used locally without a third-party service.
For Vue 3, I'm not aware of the library yet, but we plan with Kolby, basically after developing the module for Next, to refactor it in the next version into a Vue plugin, so that we will have the same experience for Vue applications without actually having the Next module. So right now it's only in Next, but the idea is to extract it to Vue and then use it in Next as a Vue plugin.
Okay, awesome! The next one is, any special considerations for optimizing images uploaded by a user? I would say the same ones, like try to, maybe because users tend to, you know, put the best quality image, because they are using it, so sometimes it's like 100% quality and it is then used as a cover of something or it's like cropped to smaller size, so maybe decrease the quality of the image, like change the format for sure, because if the user uses PNG, as you've seen in the demo, it's like 10 times bigger. So if it's possible, just try to optimize the format, the sizes as well, and, yeah, the quality. I would name those three for sure.
Makes sense, of course, from the dev side, but as an end user I always hate when I just upload a high quality picture and they ruin everything. It's like in Messenger, right? You upload the image and there is like, the quality is so bad that you can't even see yourself in the image.
Next question, is Cloudinary free? Yes, yes, they have a free tier. The one that I was using during the demo is completely free. Of course, there are some limitations as with all the tools, like with CMSs, with search engines. There are some limitations for the free tier. For example, in the case of the free tier in Cloudinary, what you do not get in a free account is, for example, removing the background from the image. Because if you go and visit the website by Colby, he made it for the Next Cloudinary, the same approach as I showed you, but for Next.js. He's using the remove background because he has the premium account, as he is working there. I have the free account, so basically, I cannot do the removing background. When you try to send a request with the removing background parameter in the request, it will just tell you that your account is not suitable for removing background, so things like that. In summary, yes, it is free, and I would say that the plan is quite generous. For smaller applications like portfolio, this is completely fine. For using it in a production application like enterprise, the free tier is not enough for sure. So you're an ambassador, and they didn't give you a PRO account. I created this account way before. I haven't requested yet the account for the ambassadors, but this is the plan. Yeah, you'll get it. Just joking.
The next one is, is there an open source, self-hosted alternative to Cloudinary? Yeah, so basically the IPX, the one I showed, this one is open source, you can just download it. It's also used in the NextImage. So in NextImage you can also use Cloudinary as a provider, but by default it uses IPX so that you can use it locally without any third-party service to optimize the image.
OK, thank you. Now we have a question that every developer likes.
12. Impact of Service Failures
What happens when Cloudinary or any other third-party service goes down? If our website relies on that service, it will also go down. This applies to CMS and eCommerce platforms as well. Implementing fallbacks, such as using local directory images or placeholders, can help mitigate the impact of service failures.
Now we have a question that every developer likes. What happens when Cloudinary goes down? I would say that the same as with any other third-party service. If our website is like, this third-party service is crucial, the website will be down. It's the hard truth. But it can work the same way if we based our application on, for example, the CMS or the eCommerce. What happens right now if you have an eCommerce website that the front-end is just the front-end and the eCommerce platform will be down? Let's say that Shopify for some reason is down. Basically, our shop is not working. You can, of course, implement some kind of a fallback. If the request is failing, we can just do a fallback to a local directory where we might have some images or placeholder images. With the CMS as well. If your page is based on CMS, powered by CMS, if CMS doesn't work, your website doesn't work as well. Yep. 100%.