Lesson Description
The "Custom Image Loader" Lesson is part of the full, Advanced Angular: Performance & Enterprise State course featured in this preview video. Here's what you'd learn in this lesson:
Alex explains how to use a custom image loader to serve properly sized images, leveraging CDNs like Firebase and Cloudflare for optimization. He demonstrates configuring the loader, updating image URLs, and shows the performance impact through network and Lighthouse comparisons.
Transcript from the "Custom Image Loader" Lesson
[00:00:00]
>> Alex Okrushko: All right, what can we do next? So what we can do is provide a custom loader, and this loader will help us provide the proper sizes for the image. Our images are huge, right? Our images right now we're pulling from this public, and they are huge. What I did instead, I had my CDN. I stored my images, same size images in my, say, Firebase storage, but it doesn't matter.
[00:00:40]
You could do any storage S3. This is basically GCP wrapper as well, so I'm storing my huge images somewhere else, not serving it locally. And typically in the app, you won't be serving them locally. They are static assets somewhere, right? I mean, you would in a smaller app, but in realistically in the big apps, you would store those in some kind of CDN.
[00:01:08]
So this is the CDN I'm using again, Firebase storage for this, storing my big images. Also, what I'm doing is I have my Cloudflare service. My Cloudflare service will do the image transformations. This is also CDN. It would do my transformations, so whenever I access something at my domain that I created, static assets.dev, and it will see if I'm trying to access the image.
[00:01:45]
So this does the transformations, but I can also specify where the source's image are. So for example, my images are in my Google API storage at my Firebase app directly there. By the way, here I see I can open this image here, right, so you can see it's still huge. It's even here loaded a little bit slower. But through application of transformations, I can in flight update the image size, and that's really cool.
[00:02:20]
So let's do that. So my Cloudflare, I'm using it for transformation, image transformation purposes. Let's show you how I do it. So in my providers in my config, I turn off all of these things. I can provide the image loader. So providing the image loader, image loader is used by ng-optimized image. If you don't have it, it's not going to use it.
[00:03:03]
It actually has a few default ones. I think it has like provide, provide where the image loader is coming from. Let's check. Let me just check this, where the image loader is coming from. Did I import it? Yes, it did. Angular common. I think there's like provide, you see, like let's provide Cloudflare loader, but this relies on you storing them, provide Netlify loader, provide images loader, image kits.
[00:03:33]
So there's Cloudinary, there's a few built-in providers that you just specify the URL where you're going to get it from. But because I need to store, I store my images somewhere else, I didn't want to store them on Cloudflare because that for me would be a paid service. Firebase provides it for free for me, so I'm using Cloudflare only for the transformation of the images.
[00:03:58]
So I'm providing the loader, so I'm doing the custom loader in this case. What I'm saying is, okay, use this value, and I'm going to use the value here. Use this value, I use value can take this config and fake all of this image loader image. Loader config, this is the config that's being passed from my directive itself. My event card, yes, so event card will, this directive will take a look at what's your width, height that is and source, all these things.
[00:04:44]
They'll know and it can provide it to through this config. So and I use this value, going to need a few things, and now I can construct the URL that I want to do. So I'll need to return my URL and again, see, this is I'm going to go static assets.dev. This is my Cloudflare service that does the transformations. I say, hey, this is the image.
[00:05:21]
I provide the width of the image to it, right? And I say format auto. Let me just copy that first. So this is the service that will be doing my transformations, and I request the image only with specific width. So for example, in this case, it will, where's my event card, it will look at the width of 500. It's like, hey, I need an image of the width of 500, the rest you do automatically.
[00:05:54]
But I also need to specify, because I'm not storing the images at Cloudflare, I store them at Firebase, but the images are sourced at this URL. So this is the additional appendix here. So the auto, pull them from the storage. They're public, they are right now. Get them here and that's the source, right? That's the source. One thing to note here, I do not have the images folder here, right?
[00:06:31]
I don't have the images folder like I do have in the path. Here have public images, and my database is looking for at images, right? So I want to strip that out before I make the request to for the storage. If I had the images folder, I didn't need to do anything, but I can modify this, right? So that's what I do here. I do in my source before I pass the source.
[00:07:16]
I'm going to go for this config source, and I'm going to replace, replace images with empty replace images. But I'm Terry, and here I'm using my source as well. Then it's the final source. So just a little modifications. I can see again what other things config has, right? Is placeholder loader, prop, sorts, width, like that's what it has.
[00:07:58]
Okay, let's see if it's happy. It's pro. All right, it's working. Let me restart it just in case. All right, let's see if we have any difference. So now I'm going for my events. My images are here. Let's look at the network tab. My images are now not 6 megabytes. They are like 86 kilobytes, which loads instantly. And you can see where they load it, right?
[00:08:31]
It goes to the static assets. You barely see that, but it goes to the static assets. It has some width, and then, and then loads the image. Let's see if it did any difference in the Lighthouse report. Any guesses if it did? All right, let's just do the new report. Analyze the page. 68. All right, we're getting somewhere, so it's still not liking certain things, but the page is already much faster.
[00:09:32]
Let me see. There may be data loading performances to be. And let me just do this again, and I'm going to rerun this again just to make sure that it is 68 still. 69, okay, a little bit better. But we can see we load things much faster. Our images are smaller, right? But again, it just says that our long lifetime of the cache is too much.
[00:09:59]
4 hours is pretty good actually. I think TTL you can, if it's static images, you can even do much longer. Generally, you sometimes you want to even cache them forever, and then if you have a new image, you will just update the name of the image, so it pulls the new version instead of the older one. So it's like, hey, how about cache could be improved?
[00:10:28]
All right, we have the fetch priority high, which is good as well. So things are pretty good. It's complaining about modification and unused JavaScript, which you can see how it can affect that as well. Okay, but it's already better, much better. And moreover, if we do the throttling, let's do the fast 4G. I'm going to refresh this page.
[00:11:01]
I have events loading. See images, boom, boom, boom, immediately, much faster. Are we able to use ng-optimized image for non-zoneless applications? Yes, so ng-optimized image is independent improvement. You can work with zoneless or zone applications. They are basically a way to improve images, to add a few attributes to the image, and also the ability to use custom loader if we want to, for the transformations.
[00:11:34]
I'm using the custom transformation loader. The other option would be a different approach is you can, when you are submitting your images, you can have a pipeline that creates different size for that image. So you can resize them at the build time, and then you don't need like a third-party service to transform the images, but you can have different source sets for this image.
[00:12:07]
And then what ng-optimized image does, actually, we can take a look at it, right? It does source and then it has source sets. See, it automatically adds to source sets. Let me just type this. Let me make later. So it's like, hey, if you have this image with 500, this is that, that's twice the image size and things like that. So it adds those source sets automatically, and you, and then based on the image size, you'll request different URLs for different images as well.
[00:12:42]
So that's another way to do it. Instead of the transformation service, you can pre-create multiple of those images ahead of time. And again, just a plugin Firebase has a way to do it as well. There's one of those tools that automatically will create you different sizes for the images. And you can see here, right, it's added the fetch priority.
[00:12:56]
It added like the loading and other things as well, right? So that's what the this directive does. It's like a helper to help you get the images in a better shape.
Learn Straight from the Experts Who Shape the Modern Web
- 250+In-depth Courses
- Industry Leading Experts
- 24Learning Paths
- Live Interactive Workshops