Source Code Included

Next JS Dynamic Image Placeholder Generation

Imran Sefat
4 min readOct 8, 2023
Image loading with blur
Image loading with blur hash data

I don’t think you are going to come into your web dev journey where you will build an app without an Image. I had to face arrogant clients who did not want to minimize their file size and they wanted an instant loading without any kind of layout shift in the site. I mean it does make sense not to have any layout shift cause that gives a bad score on the lighthouse report. Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. You don’t want the user to see a button randomly going to the bottom of the screen as another image loads in between, worst-case scenario the button went outside of the viewport making the user confused about what just happened.

To address these issues, you can use a placeholder or some might call it a skeleton with shimmering effects to put something where the image would show up. This article addresses this issue in a fancy way that is going to improve the user experience and the look of the site as well.

Steps to use the blur

  1. Configure the packages
  2. Generate the blur data
  3. Use the blur hash data with the Image Component

1️⃣ Configure the packages

To generate the blur data we need to use a package called: “plaiceholder”. Sounds funny but yeah. Add the package using the following command:

npm install sharp plaiceholder @plaiceholder/next

So, the first package “sharp” is used under the hood by our main package to generate the blur data.

We have the package installed, now we have to configure next js so that it works with next js. Open your “next.config.js” file and update it to the following:

And then rename the file to “next.config.mjs”. This plugin ensures that all Plaiceholder functions start in the main thread.

2️⃣ Generate the blur data

Let’s just say we have a simple page.tsx with a Next Image component taking up a URL as the src.

We are going to make a utility function so that it can be called from any component, not within this one component. Create a folder titled “utils” (up to you what you wanna name but I name utils).

Create a file titled: “blur-data-generator.ts” and copy the following:

This function gets an image URL in the params and creates a buffer using a fetch request then using that buffer it creates the blur data using the getPlaiceholder function. It uses the image as a base for generating the blur data.

Now, you might have a question looking at the code that we are doing another fetch request in the network stack how does that fix anything? There are some ways to optimize this as well. Take a look at the bonus part for more!

We are done with the functions. Now we can use this in our UI components.

3️⃣ Use the blur hash data with the Image Component

To get the blur effect while the app is loading the image we have to use two additional props to the Image component. The first one is the “placeholder” should contain “blur” value as we are doing the blur hashing and the other one should be the data for showing the blur with “blurDataURL” prop. As the name suggests, we have to pass the blur data to this prop.

To do this, we have to get the data first by calling the “getBlurData ”function we created earlier in the utils folder. Have a look at the modified page.tsx file given below:

On line 8, I am calling the function and destructuring the object to get only the “base64" we are going to need in line 19.

That’s it! 🎊

Hit refresh and try it out. Also, next js is gonna cache the data so disable cache from the network tab in dev-tools.

Bonus 👀

I mentioned somewhere along the tutorial that each time generating the blur data might be a problem. Possible solutions can be the following:

  1. Making a private API route for the function using NEXT API routes,
  2. Using Redis for caching the generated blur data.

Or you can use both together.

Let’s have a look at using the API routes first in the following section:

For this one, you can do a GET request to get the base64 of the generated image.

Now, what about using Redis? See the following:

The code is self-explanatory but yeah it’s checking if the blur data is available in Redis before generating the data. If the data is not available then it generates and then before returning it stores it on Redis.