Lazy Loading Images in Angular

Angular: The Full Gamut Edition

Charlie Greenman
August 30, 2020
4 min read

The Benefit of Lazy Loading Modules

Even though we discussed lazy loading modules, we might also want to lazy load the content inside of the lazily loaded modules. There is a very popular article from Google that is generally spread around with regards to performance for webpages. In short, it presents the a very persuasive set of data, shown above.

As we can see with the data presented above, the performance of our webpages is very important. More so it presents the data very clearly that the faster a webpage is, the higher probability there is to retain our user base.


The Idea of Lazy Loading Images

There are, of course, many different ways to increase performance. The intent of this chapter, however, is just to discuss the one performance boost that is gained by lazy loading images. The idea of lazy loading images, similar to lazy loading modules in general, is to load an image only when a user gets to that image.


It is important to note, that we do not want to lazy load all images that are present on our page. For instance, imagine that we were creating a blog for our website. On each single blog page, we have a featured image that shows up first for our blog. In addition, we have more images that show up throughout the remainder of the blog. It can be strongly argued that lazy loading should not be applied to the feature image. Because, it would potentially cause an awkward experience for the user, to load the page and then wait an additional second to see what the feature image looks like.

Therefore, when creating lazy loaded images, it is important to not create a blanket rule that will apply to all images. Rather, those images which are not primary to the page, should be lazy-loaded.


Real Talk — Implementing Lazy Loading

Within Angular, there would be a way to implement lazy loading from scratch. The simplest solution I’ve seen is wrapping an Angular Directive around the Intersection Observer api. It will allow you to determine when an element is in the viewport. This approach , works great, however, there are readily available npm plugins that do this for Angular. While the author of the aforementioned article did create their own plugin there is another that is much more mature. It implements the intersection observer as well, and is called ng-lazyload-image.


ng-lazyload-images

Razroo’s preferred Angular package for lazy loading is ng-lazyload-image. It is the most mature of all packages in the Angular eco-system, has the most stars, and fantastic documentation.

Install

npm install ng-lazyload-image --save

Setup

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { LazyLoadImageModule } from 'ng-lazyload-image'; // <-- import it
import { AppComponent } from './app.component';

@NgModule({
    declarations: [ AppComponent ],
    imports: [ BrowserModule, LazyLoadImageModule ], // <-- and include it
    bootstrap: [ AppComponent ]
})
export class MyAppModule {}

If Using IE

If want to use IE(Internet Explorer), will need to use a polyfill.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { LazyLoadImageModule, intersectionObserverPreset } from 'ng-lazyload-image'; // <-- include intersectionObserverPreset
import { AppComponent } from './app.component';

@NgModule({
    declarations: [ AppComponent ],
    imports: [
      BrowserModule,
      LazyLoadImageModule.forRoot({
        preset: intersectionObserverPreset // <-- tell LazyLoadImage that you want to use IntersectionObserver
      })
    ],
    bootstrap: [ AppComponent ]
})
export class MyAppModule {}

Example Use Case

The following is an example use case, of how to create a lazy loaded image with ng-lazy-load:

import { Component } from '@angular/core';

@Component({
  selector: 'image',
  template: `
    <img [defaultImage]="defaultImage" [lazyLoad]="image">
  `
})
class ImageComponent {
  defaultImage = 'https://www.placecage.com/1000/1000';
  image = 'https://images.unsplash.com/photo-1443890923422-7819ed4101c0?fm=jpg';
}

The package also has examples for multiple other use cases such as background images, responsive images, async images(i.e. | async) etc.

Transitioning Photos

Something that you might want to do is add a transition to your photo, so that it swaps out the defaultImage with the lazyLoaded image. Doing something like this would be relatively straightforward. For instance:

img.ng-lazyloaded { 
  animation: fadein .5s;
}
@keyframes fadein {
  from { opacity: 0; }
  to { opacity: 1; } 
}

That is all it would take to put a transition effect on your photos.

Hooking Up Lazy Loading To Our Back End

I believe readers are savvy enough to figure out how to hook up the backend to their component, without the need of this book. Therefore, I just wanted to mention the strategy really quick. In short, you would get all image URLs from the actual GraphQL query. You would put them underneath the lazyload directive. Just like that, you have lazy-loaded configured.

That’s it! You are all set to set up lazy loading for images within Angular.

More articles similar to this

footer

Razroo is committed towards contributing to open source. Take the pledge towards open source by tweeting, #itaketherazroopledge to @_Razroo on twitter. One of our associates will get back to you and set you up with an open source project to work on.