Next.js 10 Image Optimisation Component and next-optimized-images, a brief comparison

jameswallis

James Wallis

Posted on October 28, 2020

Next.js 10 Image Optimisation Component and next-optimized-images, a brief comparison

Edit: Since writing this blog I've been able to try the built in Next.js Image optimisation. I found that due to the requirements of either having to specify a width and height or use layout="fill" and a parent component to size the images, it was impossible to allow my image to be dynamically resized by the height of it's container e.g. no more height="100%". This requirement seems to be causing issues to other peoples projects as well. Hopefully they will fix it in the future! For now, I'll be sticking with next-optimized-images

Next.js 10 was released yesterday as part of the first ever Next.js Conf, an interactive online experience consisting of various talks centred around all things Next.js.

One groundbreaking feature announced as part of version 10 is the all new Image Component and Automatic Image Optimisation. The Image Component is designed to be a drop in replacement for existing <img> elements and when used will:

  1. Reduce the size of your image.
  2. Optimise it for various viewpoints such as desktop and mobile screens.
  3. Lazy load images so that ones further down the page are loaded later and ones at the top are prioritised.
  4. Where possible, convert your image to next generation formats such as WebP (30% smaller than JPEG).

These optimisations add up and have the potential to make a website much faster just by changing an <img> to an <Image>.

Some interesting figures about Image Optimisation from the Next.js 10 blog:

  • "Images take up 50% of the total bytes on web pages".
  • "Half of all images are over one megabyte in size".
  • "Users browse the web using their phones, tablets, and laptops, yet images are still as a one size fits all. For example: sites load a 2000 by 2000 pixel image, but phones are only displaying it as 100 by 100 pixels".
  • "30% of images on web pages are outside of the initial viewport, meaning the browser loads images that a user does not see until they scroll further down the page".
  • "99.7% of images on websites don't use modern image formats like WebP".
  • "WebP ... is about 30% smaller than JPEG".

Read the full blog post on nextjs.org

If you've read this far I know what you're thinking... hasn't this already been done?

And the answer is, sort of...

Enter next-optimized-images

Next-optimized-images is a Next.js plugin which, as the name suggests, automatically optimises your images.

I've been using it for a couple of years and first came across it when I was building https://artistjodi.com, a website for a client that contains an almost ridiculous number of images, and it saved me from either having to manually compress each image or building a script to do it. The point is it saved me hours and gave me features I didn't even know I needed.

Next-optimized-images states that it will:

  • Reduces image size by optimizing images during build (20-60%)
  • Improves loading speed by providing progressive images (for formats that support it)
  • Inlines small images to save HTTP requests and additional roundtrips
  • Adds a content hash to the file name so images can get cached on CDN level and in the browser for a long time
  • Same image URLs over multiple builds for long time caching
  • Provides query params for file-specific handling/settings jpeg/png images can be converted to webp on the fly for an even smaller size
  • Provides the possibility to use SVG sprites for a better performance when using the same icons multiple times (e.g. in a list)
  • Can resize images or generate different placeholders while lazy loading images: low quality images, dominant colors or image outlines

From the GitHub repository

This sounds familiar to the Next.js Image component. In fact, on its canary branch (version 3) it has it's own Image component. Let's look at the differences on paper.

Quick look differences

Feature Next.js Image Optimisation next-optimized-images
Uses a custom Component X In a future release
Reduce Image Sizes X X
Optimise for various viewpoints (resize) X X
Lazy load based on page position X
Convert to next generation image formats (WebP) X X
Progressive image loading X
Inlines small images X
Adds content hash for caching X
Optimises SVGs X
Generate placeholders for images before loading X
Optimises images from Cloud Providers X ~
Easy to setup Built in NPM packages, changes to next.config.js required

So it looks like that the Next.js Image component does the basics but if you're looking for a full image optimisation solution for Next.js, next-optimized-images still has it's place.

Ease of use

Example Next.js code:

function DemoMyImage() {
  return <img src="./picture.jpg" alt="a picture" height="200" width="100" />
}
Enter fullscreen mode Exit fullscreen mode

Next.js Image Component

To change the example code to use the <Image> component, it just needs to be imported.

import Image from 'next/image'

function DemoMyImage() {
  return <Image src="./picture.jpg" alt="a picture" height="200" width="100" />
}
Enter fullscreen mode Exit fullscreen mode

Next-optimized-images (V2/current)

Next-optimized-images also has a V3 on the way with it's own Image component, I've written about it a little further down.

As next-optimized-images is an external plugin, it's a little more complicated to setup.

First we need to install the package and any packages needed for image optimisation. As the example image is a JPEG, we need to add the imagemin-mozjpeg and webp-loader packages to enable JPEG optimisation and WebP conversion. We will also add the responsive-loader package which enable image resizing.

npm install -s next-optimized-images imagemin-mozjpeg responsive-loader sharp
Enter fullscreen mode Exit fullscreen mode

Next we need to update the Next.js config to enable the image optimisation.

// next.config.js
const optimizedImages = require('next-optimized-images');
module.exports = optimizedImages();
Enter fullscreen mode Exit fullscreen mode

With image resizing, JPG optimisation and potential WebP conversion, the example using the plugin will be:

function DemoMyImage() {
  const imgSrc = require('./picture.jpg?resize&size=100');
  return <img src={imgSrc.src} alt="a picture" />
}
Enter fullscreen mode Exit fullscreen mode

Next-optimized-images (V3/Canary)

Next-optimized-images V3 is a complete re-write of the existing extension that hopes to squash all existing bugs with V2. In V3 you can import an image using import rather than require and take advantage of an <Img> Component like the Next.js built in one.

Setup for V3 is on the canary branch.

Let's take a look at the usage of the <Img> Component.

import Img from 'react-optimized-image';
import MyImage from './picture.jpg';

function DemoMyImage() {
  // Attempt WebP conversion and fallback to JPEG
  <Img src={MyImage} webp sizes={[100]} />
}
Enter fullscreen mode Exit fullscreen mode

As you can see it's much cleaner than V2's require system using queries to do resizing (?resize). It also appears much more customisable than the Next.js <Image> component as it can take advantage of all the functionality that next-optimized-images has gained over the years.

V3's release date is currently unknown and it may contain bugs so if you want to use a custom image Component, the Next.js one is the safer bet as it is fully released and supported.

Code Comparison Summary

Although the initial setup was expectedly longer than the built-in component, once it's done you can just add a require() around the existing file path.

 Conclusion

The new built-in Image Component is a great starting point when optimising your images but next-optimized-images still appears to be capable of handling more image types and providing more customisation such as progressive image loading and placeholders.

That said, in projects that use a small number of images the Next.js Image Component is likely the better fit as it works out the box and will optimise images without any further configuration. I'm sure in the future the Image Component will only get better so it'll be interesting to see what it does differently to the next-optimized-images plugin, especially since V3 contains it's own React Component.

All the new features in version 10 provide yet more reasons for Next.js to become your go-to React.js framework and I am excited to try them all - especially the Image Component.

What do you think about the new Image component? Let me know in the comments and drop a reaction!

💖 💪 🙅 🚩
jameswallis
James Wallis

Posted on October 28, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related