DEV Community

sanish
sanish

Posted on • Edited on

React Progressive Graceful Image with Lazy Loading

TLDR;

  • npm i react-progressive-graceful-image

  • Supports features like Custom Image Placeholder/Loader Component, srcset, lazy Loading, Graceful Loading, Progressive Image Loading.

  • Use of Intersection Observer and navigator.onLine (Better performance and Optimization)

Motivation

I was working on an e-commerce PWA and you know what is there on an e-commerce platform? Images, more images and well, a lot more images. The truth is, with the increase in internet speed, images are everywhere now, be it e-commerce/social media/blog/news/dating or any other site.

Image is Everything, Everything is Image — (Credit: Rockstar movie)

So what’s the big deal in loading images? Just make an img tag and done!! I am sure you are thinking it’s not even that easy. The problem is loading of an image takes time. Particularly, when there is a huge number of high-quality images on a single page.


Solutions

To give a better user experience, various things can be done:

  • Image Placeholder — Keep a static image(png/svg) / a loader(gif) / a colored background div(usually grey) / a grey div with shimmer effect like the one below, until the real image is downloaded.

Image Loading with Shimmer effect animated placeholder

  • Progressive JPEG — Use Progressive JPEG instead of a normal Baseline JPEG image, although it’s not much in the control of client-side code. Here is an example.

Baseline Image vs Progressive Image Loading

  • Lazy Loading — Don’t load an image until it is visible or close to the viewport. Below gif explains it.

Lazy loading

  • Graceful Loading — Display the placeholder until the image is fully loaded and retry image loading even if network error happens(mostly when a device switches network for some reason like power/network failure).

  • Progressive Image Loading — Sites like medium, facebook, etc uses a tiny version of the real image with blur filter until the real image is downloaded and then uses some CSS transition to replace the tiny one. Here is an example.

Progressive Image Loading

  • srcset attribute —used to let the browser automatically choose image based on device screen size and/or device pixel ratio(DPR).

Huh? That’s a lot of information and so many things can be done. Now to build an component in ReactJS with one or two of the above features is easy, but how about building an component with all of the above features?

Drumroll, please!! Enter the savior, the superhero…

npm i react-progressive-graceful-image


Some FAQs

  • Why do we need various combinations together, why not implement just one variation, for example - Progressive Image Loading?

— Let’s take an example. Home Page of an e-commerce has various sections, some with ads for which tiny images might be available. Since it’s a landing page that gets maximum eyeballs of visitors, hence better user experience is required. But “Search result page” or “Product description page” may serve images for which tiny images are not available(why you ask? One of the reasons, it’s costly). So we need let’s say, a grey div placeholder with shimmer effect. And as a developer, you don’t want to make multiple components for images. Similarly, there can be other use-cases. You get my point.

  • Why do we use this npm package? Is there any other better package?

— I found some really good packages like react-shimmer, react-graceful-image, and react-progressive-image but honestly speaking, most of them lacked one or more important features. Like, react-graceful-image lacked shimmer effect and react-progressive-image lacked lazy-loading and graceful-loading. In fact, I started by forking react-progressive-image and new features from react-graceful-image. Later improved upon them.

  • What about performance, optimization, and browser support?

— Currently, the package size is 3.6kb. I have used Intersection Observer for Lazy Loading (Better Performance) as compared to throttling scroll event listeners which run on the main thread. One big reason, Intersection Observer runs on a separate thread in the Browser. Read more about it here and see it in action at @researchgate/react-intersection-observer which is the only dependency of this package.

Also, the retry strategy for graceful loading in react-graceful-image was not quite optimized. It would also hang the screen sometimes when the device goes offline and a lot of image requests are sent simultaneously which would fail anyway. So I have used navigator.onLine based strategy for optimization.

In case Intersection Observer is not supported by a browser, its polyfill is available here.


Usage

Great!! How do I use it? Any demo?

here you go…

react-progressive-graceful-image-simple-example - CodeSandbox

CodeSandbox is an online editor tailored for web applications.

You can find more examples and documentation on npm or github.

In case you find any issues or improvements, PRs and contributions are welcome on github.


Extra Browny Stuff: Always use padding-percentage solution to wrap the component to prevent any reflow and improve browser performance. Here is a small code snippet to make the best use of this logic.


Thank you for reading this article. Please share if you liked it.

Top comments (0)