Search code examples
angularimageseoserver-side-rendering

How to deal with image lazy loading when you have a SSR web app?


So, I read a bunch of articles and Google docs about lazy loading images in a proper way nowadays, and found this solution:

  • Use the newer loading="lazy" in <img /> tags where it's supported
  • Fallback to the Intersection Observer where it is not

So far so good, but when I am delivering my web app with server-side rendering (in my case an Angular 8 app with ANgular Universal enabled), and I can't verify which browser my client uses when rendering, just when the app is rendered and then the lazy loading doesn't work.

I am using this great approach from Natanel: Link

import { Directive, ElementRef } from '@angular/core';

@Directive({ selector: 'img' })
export class LazyImgDirective {
  constructor({ nativeElement }: ElementRef<HTMLImageElement>) {
    const supports = 'loading' in HTMLImageElement.prototype;

    if (supports) {
      nativeElement.setAttribute('loading', 'lazy');
    }
  }
}

The problem is that this if is always falsy in server.


Solution

  • images will still be downloaded as a separate http calls, so logic on the server won't work as you probably expect. what to do really depends on how do you handle the "unsupported" case.

    case 1: you want to just leave the image as non lazy. If so - just add the attribute when this logic is used on the server environment. for newer browsers - these images will be lazy. for older browsers - your images will be loaded just as simple images, just the same as you directive logic.

    case 2: you want to fallback to IntersectionObserver. In this case just skip the logic in this directive when running on server. it will be handled on client.