Utilizing the Next.js App Router, I attempted to retrieve all my markdown posts stored in files by scanning a directory using fs.readdirSync()
. While everything worked flawlessly locally, upon deploying on Vercel, an unexpected issue arose.
The code was encapsulated within a function and invoked twice on different pages. Surprisingly, one of them functioned as intended while the other triggered an error:
Error: ENOENT: no such file or directory, scandir 'data/posts/'
.
Here is the function:
const fs = require('fs');
export async function FetchPosts() {
// read all markdown files in this dir
// get an array containing filenames
let posts = fs.readdirSync('data/posts/');
try {
let data = [];
let promises = [];
posts.forEach((filename) => {
let promise = new Promise((resolve, reject) => {
// use async so i can import module dynamically
(async () => {
// i used a webpack plugin called frontmatter-markdown-loader
// this allows me to import markdown files as a module
await import(`data/posts/${filename}`)
.then((post) => {
// substring is to remove `.md` in the filename
const slug = filename.substring(filename.indexOf('.'), 0)
resolve({
"slug": slug,
"attributes": post.attributes,
"html": post.html
})
}
)
})();
})
promises.push(promise);
})
data = await Promise.all(promises);
// sort posts by date
data.sort((a, b) => {
let dateA = new Date(a.attributes.date);
let dateB = new Date(b.attributes.date);
return dateB - dateA;
})
return data
} catch(err) {
throw err
}
}
This page functions correctly:
import { FetchPosts } from '@/lib/fetchPosts'
// ...
export default async function Blog() {
const posts = await FetchPosts();
return (
<>
<Header />
<article>
<Heading />
<Padding>
<BlogCategories />
<BlogList posts={posts} />
</Padding>
</article>
</>
)
}
However, this triggers
Error: ENOENT: no such file or directory, scandir 'data/posts/'
.
import categories from "@/data/categories.data";
import { FetchPosts } from "@/lib/fetchPosts";
// ...
export default async function Page({ params }) {
const posts = await FetchPosts();
let data = [];
posts?.map((post) => {
if (post.attributes.category == params.slug)
data.push(post)
})
return (
<>
<Header />
<article>
<Heading />
<Padding>
<BlogList posts={data} />
</Padding>
</article>
</>
)
}
Surprisingly, this code builds successfully without any deployment errors. The issue only arises when attempting to access the website.
I'm perplexed and unable to discern the root cause behind this strange behavior.