Skip to content

Commit b094e01

Browse files
post: blog for NgOptimizedImage directive in Angular 15 (#58)
* post: Added blog for Image optimisation techniques and performance improvements with the new NgOptimizedImage directive in angular 15
1 parent 0af9ff3 commit b094e01

15 files changed

+237
-0
lines changed

_data/authors.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,8 @@ Anjali Goyal:
6464
name : "Anjali Goyal"
6565
avatar : "assets/images/avatars/anjali_goyal.jpg"
6666
bio : "Senior QA Engineer - Customer Success"
67+
68+
Manisha Arya:
69+
name : "Manisha Arya"
70+
avatar : "assets/images/avatars/manisha_arya.jpg"
71+
bio : "Senior Frontend Engineer - R&D"
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
---
2+
title: "NgOptimizedImage Directive in Angular 15"
3+
excerpt: "Image optimisation techniques and performance improvements with the new NgOptimizedImage directive in Angular 15"
4+
tags: Web NgOptimizedImage Angular
5+
authors:
6+
- Manisha Arya
7+
header:
8+
teaser: /assets/images/post/ng-optimized-image-directive-in-angular-banner.png
9+
teaser_alt: NgOptimizedImage Directive in Angular 15
10+
category: Frontend
11+
---
12+
13+
![](/assets/images/post/ng-optimized-image-directive-in-angular-banner.png)
14+
15+
# Introduction
16+
17+
Images constitute a major part of any web application. They heavily impact the page loading times and performance of the web page.
18+
19+
They are one of the main contributors to the [**Core Web Vitals**](https://web.dev/vitals/#core-web-vitals"), identified by Google, to measure website performance.
20+
21+
The metrics that make up the core web vitals are as follows:
22+
23+
{% include
24+
components/figure.html
25+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-0.png"
26+
description="Core Web Vitals"
27+
%}
28+
29+
To improve the Web Vitals metrics, loading times, and responsiveness of a single-page-application, Angular has introduced the [NgOptimizedImage](https://angular.io/api/common/NgOptimizedImage) directive with Angular v15. This new directive improves image loading performance by providing image optimisation techniques and also enforcing best practices.
30+
31+
# Default `<img>`Tag
32+
33+
Before diving into the key features of the `NgOptimizedImage` directive, let's first examine how the default `<img>` tag functions and the extra optimisation techniques that can be implemented with it.
34+
35+
**No default lazy loading:** the following example includes 6 `img` tags which the browser requests and eagerly loads all of them.
36+
37+
{% include
38+
components/figure.html
39+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-1.png"
40+
description=" List of images in HTML"
41+
%}
42+
43+
This can be costly on low-bandwidth devices when there are pages with huge number of images.
44+
45+
{% include
46+
components/figure.html
47+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-2.png"
48+
description="All images eagerly loaded with img directive"
49+
%}
50+
51+
This problem can be mitigated by using the `loading="lazy"` attribute. It defers the loading of images until they are needed.
52+
53+
Prioritising the loading of a critical image can also be done using the `fetchPriority` attribute. For example, by using `fetchpriority="low"` for images in a carousel.
54+
55+
{% include
56+
components/figure.html
57+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-3.png"
58+
description="Image optimisation with img tag"
59+
%}
60+
61+
# `NgOptimizedImage` directive
62+
63+
This directive includes built-in image optimisation techniques and improves the website’s performance with minimal configuration.
64+
65+
## Integrating `NgOptimizedImage`
66+
67+
To integrate the `NgOptimizedImage` directive, follow these steps:
68+
1. Import `NgOptimizedImage` into your standalone component or module.
69+
2. Replace the `src` attribute of the image with `ngSrc`.
70+
3. Specify the `width` and `height` attributes that must be specified for the `NgOptimizedImage` directive in one of the following ways.
71+
72+
```
73+
//import in module
74+
import { NgModule } from '@angular/core';
75+
import { CommonModule, NgOptimizedImage } from '@angular/common';
76+
@NgModule({ imports: [CommonModule, NgOptimizedImage], })
77+
78+
// use in component
79+
import { Component } from '@angular/core';
80+
@Component({
81+
selector: 'app-optimised-image-catalog',
82+
template: `<img ngSrc="blog-food-img" width="500" height="300" alt="Food Blog Image"/> `,
83+
})
84+
```
85+
86+
Alternatively, you can add it directly in a standalone component.
87+
88+
```
89+
import { Component } from '@angular/core';
90+
import { CommonModule, NgOptimizedImage } from '@angular/common';
91+
@Component({
92+
selector: 'app-optimised-image-catalog', standalone: true,
93+
imports: [ CommonModule, NgOptimizedImage ],
94+
template: ` <img ngSrc="blog-food-img" width="500" height="300" alt="Food Blog Image" /> `, })
95+
```
96+
97+
## Key features of `NgOptimizedImage`
98+
99+
The following are the main highlights of this directive:
100+
101+
### Intelligent lazy loading
102+
103+
By default, the directive lazy loads non-critical images and only eagerly loads images marked with the `priority` attribute. This ensures that most images are loaded optimally.
104+
105+
{% include
106+
components/figure.html
107+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-4.png"
108+
description="Six img tags in HTML"
109+
%}
110+
111+
The following shows that the browser only requests 4 images that are on the view port with the `NgOptimizedImage` directive.
112+
113+
{% include
114+
components/figure.html
115+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-5.png"
116+
description="Images loaded lazily"
117+
%}
118+
119+
### Serve responsive images
120+
121+
Before implementing responsive images using the directive, you must consider how the `ngSrcset` and `sizes` attributes work.
122+
123+
```
124+
<img ngSrc="business.png" ngSrcset="100w, 200w, 300w" priority sizes="50vw">
125+
```
126+
127+
* `ngSrcset` specifies three different image sources with widths of 100w, 200w, and 300w. The directive supports both width descriptors for example, `100w`, and [density descriptors](https://web.dev/codelab-density-descriptors/#use-density-descriptors-to-serve-multiple-images), for example,`1x`.
128+
129+
* `sizes` specifies the width of the image container or layout in CSS units, with different sizes for different screen widths.
130+
131+
132+
#### srcset
133+
134+
* The `srcset` attribute can be manually defined by providing your own `ngSrcset` attribute, as given in the example above.
135+
136+
* For responsive images, to automatically generate the `srcset` attribute, you only have to define the sizes attribute. For example, if your image takes 50% of the viewport, set the the size to 50vw and the browser selects the image in the `srcset` that is closest to 50% of the viewport width.
137+
138+
* If you have varying image widths for different sizes of screens you can use media queries. For example in a grid layout, you want image to be 100 percent of screen on devices under 768px wide, else it should be 50%. You can achieve this in the following way:
139+
140+
```
141+
<img ngSrc="business.png" width="400" height="200" priority sizes="(max-width: 768px) 100vw, 50vw">
142+
```
143+
144+
### Image loader
145+
146+
On a web page, most images are served without regard for the size of the image container. This means that even if you only need a 200 pixel x 100 pixel image, a 2000 pixel x 1000 pixel image is downloaded.
147+
148+
This can be solved by providing an image loader function. This is a function that modifies the provided `src`, and generates multiple URLs to request the image in different sizes. These multiple URLs are used in the automatic [srcset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/srcset") generation, so that the images are served with respect to the viewport size.
149+
150+
{% include
151+
components/figure.html
152+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-6.png"
153+
description="NgOptimizedImage automatically sets srcset attribute based on width attribute"
154+
%}
155+
156+
#### `NgOptimizedImage` loader API
157+
158+
The Angular directive provides a built in loader API for third-party image services such as Imagekit, Cloudfare, Imgix. For more information see [the Angular documentation](https://angular.io/guide/image-directive#configuring-an-image-loader-for-ngoptimizedimage).
159+
160+
In the following example, the directive creates two image URLs in `srcset` for the different widths and density of an image for an image of size 50\*50.
161+
162+
```
163+
// in module providers add
164+
import { provideImageKitLoader } from '@angular/common';
165+
providers: provideImageKitLoader('https://ik.imagekit.io/Your-ID')
166+
167+
// in markup img tag
168+
<img priority ngSrc="custom-img.webp" width="50" height="50" alt="custom image"/>
169+
170+
//in DOM img tag is changed to this
171+
<img _ngcontent-stl-c204="" priority="" ngsrc="custom-img.webp" width="50" height="50"
172+
alt="custom image" ng-reflect-priority=""
173+
ng-reflect-ng-src="custom-img.webp" ng-reflect-width="50" ng-reflect-height="50"
174+
loading="eager" fetchpriority="high" ng-img="true"
175+
src="https://ik.imagekit.io/ith29bzjr/tr:q-auto/custom-img.webp"
176+
srcset="https://ik.imagekit.io/ith29bzjr/tr:q-auto,w-50/custom-img.webp 1x, https://ik.imagekit.io/ith29bzjr/tr:q-auto,w-100/custom-img.webp 2x">
177+
```
178+
179+
#### Custom loaders
180+
181+
If your image service is not provided by the `NgOptimizedImage` default loaders, you can create your custom loader as shown in the following example.
182+
183+
> **_NOTE:_** You must include a width check for creating the URL otherwise the provider generates the src with an undefined width.
184+
185+
```
186+
// in module add to providers
187+
import { NgOptimizedImage, IMAGE_LOADER, ImageLoaderConfig } from '@angular/common';
188+
[{ provide: IMAGE_LOADER,
189+
useValue: (config: ImageLoaderConfig) => {
190+
const url = config.src && config.width ? `./assets/content/${config.src}-img-${config.width}.webp` : `./assets/content/${config.src}-img.webp`;
191+
return url; } }],
192+
193+
// in markup
194+
<img priority ngSrc="custom-img" width="50" height="50" alt="custom image"/>
195+
196+
// in DOM the img tag is changed to this
197+
<img _ngcontent-btb-c158="" ng-reflect-ng-src="business" ng-reflect-width="400" ng-reflect-height="400"
198+
alt="business" width="400" height="400" loading="lazy" fetchpriority="auto"
199+
ng-img="true" src="./assets/content/business-img.webp"
200+
srcset="./assets/content/business-img-400.webp 1x, ./assets/content/business-img-800.webp 2x">
201+
```
202+
203+
### preconnect image URL
204+
205+
`NgOptimizedImage` throws a warning in browser console if there is no `preconnect` tag for the third-party image URLs in the head of the page in `index.html`. For more information on preconnect, please refer [here](https://web.dev/preconnect-and-dns-prefetch/).
206+
207+
`<link rel="preconnect" href="https://my.cdn.origin" />`
208+
209+
{% include
210+
components/figure.html
211+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-7.png"
212+
description="Browser Warning without preconnect image url"
213+
%}
214+
215+
## Performance results
216+
217+
In the following example, an [Angular App](https://github.com/manisha-backbase/image-optimisation-angular) was created with two pages: one using the Angular `NgOptimizedImage` directive, and one with the native image tag. The app was [Deployed](https://image-optimisation-angular.vercel.app/ngoptimized-img-list) and the results compared using [PageSpeed](https://pagespeed.web.dev/).
218+
219+
{% include
220+
components/figure.html
221+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-8.png"
222+
description="Results with native image tag"
223+
%}
224+
225+
{% include
226+
components/figure.html
227+
url="/assets/images/post/ng-optimized-image-directive-in-angular-15-9.png"
228+
description="Results with NgOptimizedImage directive"
229+
%}
230+
231+
## In conclusion `NgOptimizedImage` means significant improvements...
232+
The PageSpeed results for the application using `NgOptimizedImage` show a significant reduction in time for the largest contentful paint. The intelligent lazy loading feature also improves the cumulative layout shift. In conclusion, the `NgOptimizedImage` directive drastically improves the performance of your application by enforcing the best practices for image optimisation.
135 KB
Loading
-388 KB
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)