How to run a script build time in Next.js
I was trying to see if moving my blog (based on Hugo) to Next.js was a good move (it wasn't) and I found a problem.
I had to change the path of each of my images because Hugo allows a post to be in the same folder as the markdown file, while Next.js does not.
But I didn't want to disrupt my workflow. It's so nice that I can get my images in the same folder as the markdown file. It's very easy for authoring and maintenance.
So I got this plan: at build time I'd go through all the posts, gather the images, and create a folder for each of the posts in /public/images.
The truth is, if you want to build the most-accessible product possible, you need to use both pixels and ems/rems. It's not an either/or situation. There are circumstances where rems are more accessible, and other circumstances where pixels are more accessible.
I had to change each image path in the markdown, and that was the easiest thing.
Then I had to run a post-build command by creating a postbuild.mjs file whose job was to go through my content/posts folder, and copy each image in public/images:
import fs from 'fs'
import path from 'path'
const source = './content/posts'
const destination = './public/images'
const posts = fs.readdirSync(source)
fsExtra.emptyDirSync(destination)
fs.mkdir(destination, () => {
posts.map((slug) => {
if (slug === '.DS_Store')
return
fs.mkdir(`${destination}/${slug}`,
() => {
fs.readdirSync(`${source}/${slug}`)
.filter((item)
=>
['.png',
'.jpg', '.jpeg',
'.gif'].includes(path.extname(item))
)
.map((item)
=> {
fs.copyFile(
`${source}/${slug}/${item}`,
`${destination}/${slug}/${item.replace(/
/g, '-')}`,
()
=> {
console.log(`${destination}/${slug}/${item}`)
}
)
})
})
})
})
);
Then add a postbuild entry in your package.json file scripts:
{
...
"scripts": {
"build": "next build",
"postbuild": "node
./postbuild.mjs",
"dev": "next dev",
"start": "next start",
...
}
}
using the same technique you could create a prebuild entry that's run before the build.