Properly Encoding Static Image Data for NextJS

Viewed 173

I'm trying a purely static approach on a new project Next v12 project, building up 5-6 data files to feed into getStaticProps. Here's one of the shapes of the data file (but they're all similar):

import SqAshland1 from '../../public/best-places-imagery/square-ashland.jpg'

const bestPlacesList = [
   {
    "cityName": "Ashland",
    "state": "WI",
    "country": "US",
    "imageSquare": SqAshland1,
    "slug": "ashland-wi"
   }, 
   ...
]

const encodeBestPlacesList = JSON.stringify(bestPlacesList)
export default bestPlacesList

This is what it looks like when I inject this file in my /pages/best-places/[slug].js:

export async function getStaticProps({ params, preview = false, previewData }) {
  
  const parsedBestPlacesList = JSON.parse(bestPlacesList)
  const cityData = parsedBestPlacesList.find( city => city.slug === params.slug )

  return {
    props: {
      preview,
      cityData: cityData,
    },
    revalidate: 60,
  };
}

export async function getStaticPaths() {
  const cities = JSON.parse(bestPlacesList);

  return {
    paths: cities?.map( (city) => ({
      params: { slug: city.slug }
    })),
    fallback: false,
  };
}

It's working well, but the images keep breaking when I deploy. This makes me think I need to do base64 encoding for the images but where do I do this so I don't break Next's image fetching? Curious if anyone has tried this approach and knows how to balance Next and Node just right.

1 Answers
  1. Personally, I think base64 would be right to use here. It would be best to use bease64 encoding together with the data URI scheme (https://en.wikipedia.org/wiki/Data_URI_scheme).

You could use the following helper function to get an image base 64 encode with the URI scheme

// Helper function
function base64EncodeJpg(file) {
    return "data:image/jpg;base64," + fs.readFileSync(file, 'base64');
}
  1. Use the helper function when you create the bestPlacesList
const bestPlacesList = [
   {
    "cityName": "Ashland",
    "state": "WI",
    "country": "US",
    "imageSquare": base64EncodeJpg('../../public/best-places-imagery/square-ashland.jpg'),
    "slug": "ashland-wi"
   }, 
   ...
]
  1. to make sure the paths will work both in production and development you could make use of a .env file where you define a base path for the image assets and use this instead of the relative paths. https://nextjs.org/docs/basic-features/environment-variables
Related