Newly released Angular 14.2 comes with a nifty image optimization feature that can be used to improve the performance of your application.
In this blog post, we will take a look at the exciting new NgOptimizedImage
directive and explain how we used it to make this example e-commerce application perform up to 50% better on Lighthouse scores!
What is NgOptimizedImage?
NgOptimizedImage is a Directive focused on improving Image Loading performance. As a happy side-effect, NgOptimizedImage
enforces best practices and improves Core Web Vitals scores, which might help your application rank higher on search engines.
Important Note: NgOptimizedImage
is on Developer Preview. Features on Developer Preview might change APIs without notice. If you decide to use NgOptimizedImage
on production, be aware when updating your application.
How to Use NgOptimizedImage
In order to use the NgOptimizedImage
directive, identifiable by the selector img[rawSrc]
, you need to import NgOptimizedImage
into your Module or Standalone Component.
import { NgOptimizedImage } from '@angular/common';
Set Up an Image Loader
Image Loaders are tools that host images and provide optimization services such as image resizing or compression.
Angular now provides popular Image Loader configurations out of the box. In our e-commerce application example, we set up ImageKit with the provideImageKitLoader
function, whose path
argument is the default URL endpoint for an account.
// src/app/app.module.ts
// ... other imports
import { NgOptimizedImage, provideImageKitLoader } from '@angular/common';
@NgModule({
declarations: [AppComponent, HomeComponent, CartComponent],
imports: [BrowserModule, AppRoutingModule, ScullyLibModule, NgOptimizedImage],
providers: [provideImageKitLoader('https://ik.imagekit.io/fabioemoutinho')],
bootstrap: [AppComponent],
})
export class AppModule {}
Understand NgOptimizedImage Properties
NgOptimizedImage
adds additional properties to an img
tag:
rawSrc: string
: instead ofsrc
full URL,rawSrc
represents the source image name-
rawSrcset: string
: a comma-separated list of width or pixel density descriptors. Not required, but recommended. Usually used in conjunction with sizes attribute if you want to provide different image sources for different viewport sizes.
<!-- example taken from https://angular.io/api/common/NgOptimizedImage#properties --> <img rawSrc="hello.jpg" rawSrcset="100w, 200w" /> <!-- img tag above would output an img tag similar to the img below --> <img src="path/hello.jpg" srcset="path/hello.jpg?w=100 100w, path/hello.jpg?w=200 200w" />
priority: boolean
: defaults to false; If true, adds multiple optimizations to the image
Images are going to be lazy-loaded by default. That is, it is going to be up to the browser to decide when to load the images. While lazy-loading an image is usually a good approach, in some cases, like when you want to make sure the browser will download critical images first, you might want to set the priority
property to true
in order to increase the performance of your app.
The NgOptimizedImage
directive also expects every image to have explicit height
and width
attributes.
Here are the changes we had to make on a component’s template to use the NgOptimizedImage
directive.
<!-- src/app/home/home.component.html ‐‐>
<picture class="picture block relative overflow-hidden">
<img
- [src]="product.image"
+ [rawSrc]="product.id + '.jpg'"
[alt]="product.title"
class="img not-loaded object-contain w-full h-full absolute top-0 left-0"
(load)="onLoadImage($event)"
(error)="onErrorImage($event)"
+ width="200"
+ height="200"
/>
</picture>
Performance Results
In our example application, we removed scully
to better measure the impact of a vanilla implementation of the NgOptimizedImage
directive on the application’s home page. We tested two different scenarios:
- https://e-commerce-no-scully-example-angular-13.vercel.app/ - Angular 13.3.11
-
https://e-commerce-no-scully-example.vercel.app/ - Angular 14.2.0, using
NgOptimizedImage
We then ran Lighthouse locally (desktop) and had the following results:
Metric | Angular 13.3.11 | Angular 14.2 with NgOptimizedImage | Impact |
---|---|---|---|
First Contentful Paint | 0.4 s | 0.3 s | 25% decrease |
Speed Index | 1.2 s | 0.6 s | 50% decrease |
Largest Contentful Paint | 1.7 s | 1.0 s | 41% decrease |
Time to Interactive | 0.5 s | 0.4 s | 20% decrease |
Total Blocking Time | 0 ms | 0 ms | - |
Cumulative Layout Shift | 0.003 | 0.003 | - |
Performance | 93 | 99 | 6.45% increase |
Even though you get excellent performance results with the automatic lazy loading of images, NgOptimizedImage
shines even brighter when combining the usage of image loaders with the rawSrcset
property and sizes
attribute. Implementing the rawSrcset
property and sizes
attribute enables you to further optimize your application for different devices, especially for mobile devices.
What’s Next for Angular’s Image Directive?
Chrome’s blog post announcement about NgOptimizedImage
directive presents an interesting roadmap, and we can expect many improvements like automatic srcset
and sizes
attributes for responsive images, automatic height
and width
attributes and more.
Angular v14.2 introduces other interesting features that we will talk about next, stay tuned on Bitovi's Twitter.
Need help staying up to date with the latest version of Angular to take advantage of these cool new features? Contact us for Angular Consulting help!
Top comments (0)