next.jsvercelmdxjs

Next App can reach a file while in localhost but not in production


I am trying to build a page that reads some content mdx files inside the src/bounties/content/bounties folder, and my app can make it work while in localhost. But, everytime I upload and host it in Vercel or in Netlify, it gives me the ENOET error.

This is the page.tsx file, where the directory is called and the mdx file is rendered with next-mdx-remote

import { type MDXRemoteSerializeResult } from "next-mdx-remote";
import { serialize } from "next-mdx-remote/serialize";
import { promises as fs } from "fs";
import { MdxContent } from "../../mdx-content";
import BountiesBreadcrumb from "@/app/components/bountiesBreadcrumb";
import path from "path";

type Frontmatter = {
  title: string;
  date: string;
};

type Post<TFrontmatter> = {
  serialized: MDXRemoteSerializeResult;
  frontmatter: TFrontmatter;
};

interface IBountyProps {
  params: {
    slug: string;
  };
}

async function getPost(filepath: string): Promise<Post<Frontmatter>> {
  const raw = await fs.readFile(filepath, "utf-8");

  const serialized = await serialize(raw, {
    parseFrontmatter: true,
  });

  const frontmatter = serialized.frontmatter as Frontmatter;

  return {
    frontmatter,
    serialized,
  };
}

export default async function Bounty({ params }: IBountyProps) {
  const filePath = path.join(
    "src",
    "app",
    "bounties",
    "content",
    "bounties",
    `${params.slug}.mdx`
  );

  const { serialized, frontmatter } = await getPost(filePath);

  return (
    <div className="text-zinc-400 p-16 border-r border-zinc-800">
      <BountiesBreadcrumb />

      <div className="py-16 max-w-4xl">
        <h1 className="text-zinc-300 font-bold text-4xl">
          {frontmatter.title}
        </h1>

        <span className="text-zinc-400 text-md mt-8">
          Published at {frontmatter.date}
        </span>

        <div className="mt-8">
          <MdxContent source={serialized} />
        </div>
      </div>
    </div>
  );
}

For example, when the user reaches the route /bounties/dynamic-sidebar, this page needs to read the file: src/app/bounties/content/bounties/dynamic-sidebar.mdx and then render it into the page layout.

There's the error message:

[Error: ENOENT: no such file or directory, open 'src/app/bounties/content/bounties/dynamic-sidebar.mdx'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'src/app/bounties/content/bounties/dynamic-sidebar.mdx'
}
[Error: ENOENT: no such file or directory, open 'src/app/bounties/content/bounties/dynamic-sidebar.mdx'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'src/app/bounties/content/bounties/dynamic-sidebar.mdx'
}
[Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.] {
  digest: '3395753351'
}

Solution

  • The problem you are facing probably has to do with the way you are generating the file path to search for. Try the following example instead, this should work:

    const workDirPath = process.cwd(); 
    const contentPath = "src/app/bounties/content/bounties";
    const filePath = path.join(workDirPath, contentPath, `${params.slug}.mdx`);
    

    As you see I use the process.cwd function in the above example, this ensures that you are pointing to your project root and only then joining your relative path to it.