Next.js lays out a pretty comprehensive way to get imagery from the /public/
folder (where the app has you store static assets). The pattern is to use fs
from Node and do the fetch in getStaticProps
.
My attempt:
export async function getStaticProps({ params, preview = false, previewData }) {
const cityData = dataFiltered.find( city => city.citySlug === params.slug )
const cityMapImagePath = path.join(process.cwd(), `/public/static-maps/${cityData.imgPath}`)
const cityMapImageRes = await fs.readFile(cityMapImagePath)
const cityMapImageProcessed = JSON.stringify(cityMapImageRes)
return {
props: {
preview,
cityData: cityData,
cityMapImage: cityMapImageProcessed
},
revalidate: 60,
};
}
This code works, but it returns a pretty weird response when I reference that object in my component:
<img src="{ "type":"Buffer", "data":[255,216,255,224,0,6,75,56,86,87,...] } />
My error has something to do with how I'm processing what fs
gives me back. Do I need to encode my jpeg into base64
to get Next to use it? This answer suggests stringifying and then parsing (didn't work for me). Or maybe I need a full blown endpoint to do this? Next isn't very clear on how to get imagery from getStaticProps into the component above it - perhaps you know how?
What I ended up doing for the fetch in getStaticProps
:
export async function getStaticProps({ params, preview = false, previewData }) {
const cityData = dataFiltered.find( city => city.citySlug === params.slug )
const cityMapImagePath = path.join(process.cwd(), `/public/static-maps/${cityData.imgPath}`)
let cityMapImageRes, cityMapImageProcessed
try {
cityMapImageRes = await fs.readFile(cityMapImagePath)
cityMapImageProcessed = Buffer.from(cityMapImageRes).toString('base64')
} catch {
cityMapImageProcessed = null
}
return {
props: {
preview,
cityData: cityData,
cityMapImage: cityMapImageProcessed
},
revalidate: 60,
};
}
Also make sure up in the component, you are properly encoding your image source as base64
with the data:image/png;base64,
prefix. This was a silly mistake that cost me an hour of debugging:
<img src={`data:image/png;base64,${cityMapImage}`} alt='Alt text here' />
Finally, also note that Next.js when used with Vercel will impose a hard, 50MB cap (compressed) on the serverless function used to process your page
file request. If you're doing a [slug].js
template, all the assets for EVERY page generated will count towards that cap. You'll hit it pretty fast on deploy, so double check yourself.
Update 2024-02: serverless bundle size can now go up to 250MB