Next.Js Series #6 - How does 'Image' component from 'next/image' improve the web app performance
Tags: nextjs, image, webdev, javascript
Published: 2021-10-23 12:04:50

\<Image/> component is a html \<img/> extension that we can import from 'next/image'. It provides some out-of-the-box benefits which will greatly improve the performance of our web app. Here are some main features of using Image component from Next.Js that I feel most useful:
1. Improve visual stability
- By providing the defined size of image container, this could prevent cumulative layout shift (CLS). 
2. Out of the box lazy loading to improve performance.
3. Flexibility on using local static images or external resources from remote servers.
4. Images are responsive by default without further configurations.

There are required props that need to be passed into this Image component, such as:
**src** -> The source of image (can be local static image or external resource)
**width**, **height** -> These two are required for images which are imported from external resource. Next.Js can automatically determine the height and width of local static images.

Here are also some useful optional props that can be utilized to customize the behaviours of image loading:
**priority** -> This is to flag the image is supposed to be preloaded instead of lazy-loading. It is useful to improve 'Largest Contentful Paint' metric.
**loader** -> You may customize your own loader component and pass into Image component through this prop.
**placeholder**, **blurDataUrl** -> These two props are used together if you would like to put a blur image source as a placeholder before the image from 'src' gets loaded successfully. If your 'src'(.jpg, .png, or .webp) is from local file system, you do not need to provide 'blurDataUrl' and Next.Js will autopopulate.
**layout** -> This prop by default has the value of 'intrinsic', which means your image will automatically scale down to fit the width of container if smaller, up to image size if larger (which is the normal use case). 
**loading** -> This loading prop has the default value of 'lazy', which will only be rendered when the image container enters the viewport.

Here is the demonstration of Image component for a simple blog post:
```javascript
import styles from '../styles/Home.module.css';
import Image from 'next/image';
import image3 from '../images/unsplash-image-3.jpg';
import image1 from '../images/unsplash-image-1.jpg';
import image2 from '../images/unsplash-image-2.jpg';

export default function ImageBlog(){
    return (
        <div className={styles.main}>
            <h1 className={styles.title}>HELLO, THIS IS IMAGE BLOG</h1>
            <Image
                src={image3}
                alt="This is image 3"
                priority
            />
            <p>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin placerat vehicula felis eget feugiat. Nullam mattis feugiat massa, id consectetur dolor pellentesque eget. Praesent non varius est, at rutrum nisl. Maecenas feugiat vitae quam et imperdiet. Nam vulputate volutpat metus, mollis faucibus nisi eleifend ac. Integer egestas libero odio, eget ultrices leo condimentum eu. Vestibulum quis accumsan enim. Aenean sed justo tortor. Duis tincidunt elit ut vulputate commodo. Maecenas at laoreet felis, quis euismod quam. Nulla at nibh sit amet ipsum tincidunt lacinia ac eu mauris.
                Nam ornare congue egestas. In sed urna convallis, efficitur mauris et, eleifend sem. Vivamus a tempus risus. Donec dignissim nec arcu vel laoreet. Aenean ultrices porta diam. Duis vel eros vehicula, ornare felis eu, eleifend diam. Praesent sit amet erat sed libero feugiat molestie ut nec felis.
                Sed ullamcorper accumsan mi, at dignissim dolor vestibulum in. Quisque diam orci, congue in sagittis a, dapibus et odio. Praesent convallis augue non fringilla maximus. Aliquam varius ipsum ac cursus tempus. Donec lacus purus, tincidunt id ultrices ut, sollicitudin sit amet erat. Curabitur a gravida lorem, id feugiat orci. Curabitur ut pretium nulla, at pulvinar libero. Aliquam blandit neque blandit felis interdum, sed dictum ligula porttitor. Mauris condimentum ut massa in placerat. Suspendisse rhoncus finibus leo ut sagittis. Cras quis odio nec ante gravida viverra ut ac dui. Nunc tristique dictum metus vitae pharetra. Vivamus in leo vel urna sagittis efficitur sit amet a ante. Nulla pellentesque malesuada imperdiet. Phasellus non lacus consectetur, lobortis orci ac, gravida nisl. Vivamus eget lobortis elit.
            </p>
            <Image
                src={image2}
                alt="This is image 2"
            />
            <p> 
                Vivamus laoreet ex sed ligula vestibulum congue. Pellentesque porttitor tellus ut odio pulvinar sagittis. Morbi viverra tristique dignissim. Proin interdum luctus semper. Nulla at pulvinar orci. Curabitur sed dapibus sem. Mauris rhoncus aliquam felis sit amet feugiat. Curabitur ti
                ncidunt facilisis semper.
                
                Etiam sit amet risus et orci tincidunt posuere. Integer fermentum pellentesque velit nec venenatis. Etiam eleifend laoreet rhoncus. Aenean cursus tortor neque, in varius eros hendrerit quis. Maecenas eu porttitor eros. Integer quis fringilla mauris. Morbi pulvinar mattis justo a elementum. Phasellus aliquam auctor orci sit amet hendrerit. In ante nisl, pretium vitae volutpat et, semper nec ex. Phasellus leo arcu, congue eu convallis nec, varius quis sem. Quisque sodales neque blandit massa mollis bibendum. Cras nec molestie velit. Nullam vel consequat libero, non porta ipsum. Sed sit amet libero mi. Etiam iaculis ipsum sed porttitor gravida. Duis nec pretium ante.
            </p>
            <Image
                src={image1}
                alt="This is image 1"
                placeholder="blur"
            />
            <p>The image below is from external source.</p>
            <Image
                src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y932fq3n05i422leqbbs.jpg"
                alt="Test image from AWS S3"
                width="1200"
                height="1800"
             />
        </div>
    )
};
```
The first three static images are imported locally, and the last image is an external resource (I uploaded to dev.to's AWS S3). You can see that we do not need to provide 'width' and 'height' props for local images, but for externally imported one. Do note that if we want to import the image from external resource, we need to specify the url domains under 'images' in next.config.js file.

```javascript
module.exports = {
    images: {
      domains: ['dev-to-uploads.s3.amazonaws.com'],
    },
  }
```
You could also see that the images are automatically responsive.

*On iPad Pro*                         
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t4yr8mqzbnj66tzprczs.png)

*On iPhone*
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/df01u697lkbwgfya01bd.png)
                         

While you are scrolling through the page, checkout the network tab and you will notice that images are only downloaded when they enter viewport.

Hope this gives you some insights on using the Image component of Next.Js.

**Do follow me for more future articles on web design, programming and self-improvement** 😊