Start using AVIF in your Next.JS project

11.11.20 · 0 min read


NextJS images is easy! The blog you're reading uses both the latest version of React and NextJS. And not only that: the bundler automatically detects AVIF files and handles them accordingly. We didn't have to do anything for this work. That's what we call a first-class service, gentlemen!
You simply need to include the AVIF files in your project and insert them via the usual methods using HTML or CSS. No configuration is required, but you must make sure that next.config.js includes the following:
1const images = require("next-images");
2module.exports = withImages()
Next.JS will handle all the hard work behind the scenes for you. The team behind Next. JS has been working to improve image processing since version 10. They now offer both an integrated image component and a service for automatic image optimization. They describe their image component as an extension of the HTML img element designed for the modern web.
Why, you may ask? Well, images in this component are resized, optimized and automatically served in the correct format based on the visitor's device and browser. For example, you would not deliver a high-resolution image to a Nintendo Game Boy.
Furthermore, the images support the Core Web Vitals by not shifting their layouts. Furthermore, this service can also be used if the server that contains the images of the website is a CDN and not a server hosted by the website.

Next.JS image component

All in all, it's a simple "Put this image in your project, add it to the component and we'll do the entire conversion and optimization" approach. While it converts images to newer formats, it does not yet do so for AVIF. There is a on Github that refers to AVIF more than once, so hopefully we will see this supported in future versions. Finally, the images loaded via CSS will not be optimized, although we pray that this will be the case in future versions.
1import Image from 'next/image'
3      <Image
4        src="/yourmum.jpg"
5        alt="Picture of your mum"
6        width={9001}
7        height={0}
8      />

Next Optimized Images

Until this point, if you rely heavily on CSS images, you can use the third-party plugin in Next.JS called . It has many additional features, and it supports loading images with CSS, which is very useful. However, the plugin does not yet support AVIF as well. Nevertheless, the author is currently working on a complete overhaul of the entire plugin, and a Canary version is already published.

How do we at deal with AVIF support?

As we don't want to rely on Vercel or third-party components, we perform the following steps.

1. Add browser support detection script

To find out if you as a visitor have a browser with AVIF support, we have implemented the following 600-byte script in our header:
1function F(a){document.documentElement.classList.add(a)}var A=new Image;A.src="data:image/avif;base64,AAAAFGZ0eXBhdmlmAAAAAG1pZjEAAACgbWV0YQAAAAAAAAAOcGl0bQAAAAAAAQAAAB5pbG9jAAAAAEQAAAEAAQAAAAEAAAC8AAAAGwAAACNpaW5mAAAAAAABAAAAFWluZmUCAAAAAAEAAGF2MDEAAAAARWlwcnAAAAAoaXBjbwAAABRpc3BlAAAAAAAAAAQAAAAEAAAADGF2MUOBAAAAAAAAFWlwbWEAAAAAAAAAAQABAgECAAAAI21kYXQSAAoIP8R8hAQ0BUAyDWeeUy0JG+QAACANEkA=",A.onload=function(){F("avif")},A.onerror=function(){var a=new Image;a.src="data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",a.onload=function(){F("webp")}};

2. Create image component with modern markup

We have developed our own image component, which uses all the features that modern image markup should take into account, from the lazy load to the aspect ratio. We only have to choose a path and an alt text. For more information on the perfect image markup visit screenshot of code that resembles our image component

3. Convert images with sharp on build time

Finally, we have the NodeJS library integrated into our build and release script to convert images before we upload our website data to Firebase. The sharp script detects all images in a specific folder and converts them into all the different formats and sizes we need. Below is the current script we are using.
1const sharp = require("sharp");
2const fs = require("fs");
3const path = require("path");
5const output = "../public/img/";
6const input = "../images/";
7const jpgQuality = { mozjpeg: true, quality: 50, progressive: true };
8const webpQuality = { quality: 50, reductionEffort: 6 };
9const avifQuality = { quality: 45, speed: 1 };
10const sizes = [1440, 720, 360];
12fs.readdir(input, (err, files) => {
13  console.log("Found " + files.length + " files. Converting now, please be patient..");
15  files.forEach((file) => {
16    function convert(size) {
17      let fileShort = path.parse(file).name;
18      sharp(input + file)
19        .jpeg(jpgQuality)
20        .resize({ width: size })
21        .toFile(output + fileShort + "-" + size + ".jpg");
22      sharp(input + file)
23        .webp(webpQuality)
24        .resize({ width: size })
25        .toFile(output + fileShort + "-" + size + ".webp");
26      sharp(input + file)
27        .avif(avifQuality)
28        .resize({ width: size })
29        .toFile(output + fileShort + "-" + size + ".avif");
30    }
31    if (file.endsWith(".png") || file.endsWith(".jpg") || file.endsWith(".jpeg")) {
32      for (let i = 0; i < sizes.length; i++) {
33        convert(sizes[i]);
34      }
35    }
36  });
Keep in mind that this is only suitable for website without many images, as it significantly increases build time. A way to bypass that could be creating an own sharp API and using