Maximizing Performance: Comparing & Optimizing Image Sizes in Next.js

Muhammad Usman
4 min readMay 9, 2024

--

Instead of using HTML <img> tag, use <Image> tag in next.js to optimize the images

Image taken from next.js

Background:

The speed and functionality of a website are now among the most significant factors impacting the user experience in today’s digital world. Google has already said that one of the ranking factors for mobile searches is speed.

In July 2018, Google eventually made page speed a ranking factor for mobile search results. A company announcement states: “Users want to find answers to their questions quickly and data shows that people really care about how quickly their pages load. [1]

Furthermore, Next.js is the best JavaScript framework for creating high-performance, production-ready websites. To guarantee an excellent user experience, a fast website involves more than just optimizing the code — it also involves optimizing assets like images. Website speed is significantly impacted by unoptimized images, which also negatively affect your Largest Contentful Paint (LCP) metrics.

In order to address this issue, Next.js provides an additional <Image/>component that expands upon the <img>element and includes numerous essential features for automatic image optimization.

What is the Next.js Image Component?

The NextJS <Image> component is similar to the native HTML <img /> tag but with superpowers, greatly improving both the user experience (UX) and the developer experience (DX) while working with images. Today's web applications demand a more flexible and performance-oriented solution—the Next.js image component is focused precisely on this.

The <Image> component is designed to enhance image performance in web applications, managing tasks like responsive loading, adjusting image sizes based on the viewer's device, and lazy loading out-of-the-box. It also serves images in modern formats such as WebP and handles compression to strike the right balance between image quality and file size.

First you need to create a next js project by running the below command:

npx create-next-app@latest

Secondly, to test the <img> and <Image> tag on the browser, I used the car image from the google Car Image. To use the image url, first we need to allow the hostname inside the next.config.js. You can put the below code inside the next.config.js file.

module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'imageio.forbes.com',
port: ''
},
],
},
}

<img> — Unoptimized Image Tag:

  • When using the <img> tag, the browser loads the image directly from the specified source. It lacks built-in optimization features such as lazy loading and automatic optimization.
  • Responsive image handling requires manual implementation using CSS or JavaScript to ensure images scale appropriately based on screen size.
  • Images loaded using the <img> tag are typically indexed by search engines.

Now open the page.tsx file and inside the `<main>` tag, you put the below piece of code.

<img 
width={500}
height={500}
src="https://imageio.forbes.com/specials-images/imageserve/5d35eacaf1176b0008974b54/0x0.jpg?format=jpg&crop=4560,2565,x790,y784,safe&height=900&width=1600&fit=bounds"
alt="Girl in a jacket">
</img>

Open the browser and inspect the image. You can check the image properties and will find the image size of ‘72.9KB’ as shown in figure-1.

Figure-1: Render the image with <img> tag

<Image> — Optimized Image Component

  • The <Image> component in Next.js provides several built-in optimizations, including automatic image resizing, lazy loading, and priority loading for images above the fold. This helps improve performance and user experience by reducing page load times.
  • The <Image> component supports responsive image loading out of the box. It allows you to specify layout="responsive" to automatically generate responsive image variants based on the provided dimensions.
  • The <Image> component ensures that images are optimized for SEO by providing support for lazy loading, priority loading, and automatic generation of srcset attributes.

Let’s try the next.js <Image> component. Replace the<img> tag with the below code.

<Image 
width={500}
height={500}
src="https://imageio.forbes.com/specials-images/imageserve/5d35eacaf1176b0008974b54/0x0.jpg?format=jpg&crop=4560,2565,x790,y784,safe&height=900&width=1600&fit=bounds"
alt="Girl in a jacket">
</Image>

Open the browser and inspect the image. You can check the image properties and will find the image size of ‘37.1KB’ as shown in figure-2, which is approximately half with respect to the normal HTML <img> tag.

Also you can test with different display sizes like tab, mobile phone devices etc. It automatically resize the image and responsive with respect to the device resolution.

Figure-2: Render the image with <Image> component

How it works?

In Next. js, a loader function creates image URLs for different sizes, helping in automatic srcset generation for optimal viewport display. Next. js’s default loader uses its own Image Optimization API to serve optimized images, but if you’re using a CDN or custom image server usage, you need to write your own loader.

If you open the folder next → cache → images, you will find the same image with .webp extension as shown in below figure-3.

Figure-3: Image with .webP extension

Conclusion:

After test the <img> tag and with <Image> component in the next JS application, the size of images with <Image> component is considerably half compares with the <img> tag.

Overall, while the <img> HTML tag is suitable for basic image rendering, the <Image> component in Next.js offers a more robust solution with built-in optimizations for performance, accessibility, and SEO, making it the preferred choice for handling images in Next.js applications.

[1] https://www.searchenginejournal.com/ranking-factors/page-speed/#:~:text=It%20took%20nearly%20another%20decade,how%20quickly%20their%20pages%20load.

--

--

Muhammad Usman
Muhammad Usman

Responses (1)