How to use Next.js Image with a headless CMS
The Next Image component is one of the most useful and utilized features of Next.js. This component’s performance, ease of use, and flexibility contributes to the amazing developer experience that Next.js offers.
In this article we will explain how using Next.js Image with a headless CMS can automate optimizations for your website images across all devices and network speeds leading to faster website performance and a better experience for your website visitors.
Before we get into the code, let’s make ourselves familiar with the Next Image component and how we use it to load images from a headless CMS. You can also follow along with us over on YouTube, where we discuss this article in depth.
The Next Image component
The Next Image component provides cutting-edge features design for the modern web by optimizing the standard <img> component in your code. It assigns the HTML <img> srcset so that images are served responsively based on screen size. Smaller devices will be served a smaller image file with a lower resolution, and the image will scale up in resolution as the screen size increases. Next.js handles this automatically. Here’s what that looks like:
Out of the box, the Next Image component also lazily loads the images so that they become non-blocking elements. This gives our applications improved page loads and overall better Core Web Vitals. Already, we can see that Next Image handles a lot of the heavy lifting for the developer, and as you explore the component further, you will find even more useful features and use cases.
Images in a headless CMS
When using a CMS like Cosmic, we get some great features that help us store our images in one place, and at that, we can serve these images via the Cosmic API and global CDN. This means our images won’t live on just one server, but rather on a group of geographically distributed and interconnected servers. These servers will cache the images from a network location closest to the user to speed up page loads.
Why does any of this matter? User experience. As the modern web develops further and further, we find better solutions that decrease media file size, utilize non-blocking techniques, and get the content of your site to the user much quicker than ever before. This leads to higher consumer retention rates, better conversion rates, and a globally uniform experience for users.
Getting the data from our Cosmic Bucket
If you’d like to follow along with this particular use case, you can install the Developer Portfolio app template and clone the GitHub repository.
First, we must get the data from our Cosmic Bucket into our project using the Cosmic NPM package.
We create an asynchronous function to call the Cosmic API and get all of the ‘posts’ from our Cosmic Bucket by setting the query params to ‘type: “posts”’ (the name of our posts object in Cosmic).
Loading images remotely
Within the Cosmic dashboard, we can access the images we’ve uploaded to the Cosmic CDN simply by navigating to the media folder. From there, we have a few options such as grabbing the URL, the imgix URL, and adding metadata to the image, such as alt text.
For static images, we can always set the ‘src’ in our Image component to a specific URL. In your Cosmic dashboard, navigate to the ‘media’ folder, and on one of the images you’ve uploaded, click on the gear icon. Click on either the ‘URL’ or the ‘imgix URL’ selection, and copy and paste the link of the image.
In the code, it would look something like this:
Realistically, we may use a few static remote URLs for the Next Image component in a project, though most commonly we will use Static Imports (images stored locally within the directory of the project) or dynamic URLs from the headless CMS.
In our use case, we will be loading the images from blog posts. Cosmic makes it easy to do this as when you create a new object in Cosmic, you can configure the object Metafields to contain an image Metafield. As a result, creating a new article will give the user the ability to upload the image to the Cosmic CDN and attach it to the blog post all in one go.
Coding the solution
On our ‘[slug]’ pages, we can get the posts by their slug and query for the metadata. We’re using getStaticProps and getStaticPaths to get our dynamic posts.
Now let’s pass the data into our Next Image component for our blog post header.
To add a placeholder for our remote images, we can utilize imgix queries to request a low-resource version of the image. This image is very small, compressed, and blurred to ensure a very small file size. First we set the placeholder param to ‘blur’ and pass the special URL to the blurDataURL param.
With Cosmic, we can optimize our images within the dashboard by adding things like specified quality, dimensions, and compression before the images get requested. To do this, go to the Cover Image Metafield and click the Settings button. Then in the settings modal we can add some compression which will reduce the file size and improve the page load. Just like with the placeholder we used earlier, this will add imgix query params to the imgix URL.
The perfect solution
While there isn’t a perfect solution, the Next Image component does a lot of the work for us by providing features to enable us to fine-tune our images to achieve optimal image sizes and performance across all devices and network speeds ultimately leading to a better experience for our website visitors.
About Stefan Kudla
Freelance Web Developer, Music Producer, and Tech Content Creator. When I'm not creating, you can usually find me brushing my teeth with coffee or looking for the best view atop a mountain.