Reputation: 7869
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?
Upvotes: 3
Views: 1846
Reputation: 7869
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
Upvotes: 1
Reputation: 8081
All data that is returned from the getStaticProps
needs to be JSON serializable, so yes, if you want to return image there , you need to base64 encode it (this can be a problem for big images).
The other solution (if the scenario permits it) is not to do it with getStaticProps
rather load the image on demand in the front end, by hitting the API after the page has already loaded.
Upvotes: 2