mdx-js / mdx

Markdown for the component era
https://mdxjs.com
MIT License
17.77k stars 1.14k forks source link

fs__WEBPACK_IMPORTED_MODULE_0___default(...).readdirSync is not a function #2257

Closed bwkam closed 1 year ago

bwkam commented 1 year ago

Initial checklist

Affected packages and versions

I don't know what's that

Link to runnable example

No response

Steps to reproduce

Create a blog directory at pages, and inside create an mdx file. Then write some markdown and insert
<ReadingTime readTime=getReadingTime("post-1") where post-1 is the name of the mdx file.

And that's the definition of getReadingTime()

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';

export const getPosts = () => {
  const dirFiles = fs.readdirSync(path.join(process.cwd(), 'pages', 'blog'), {
    withFileTypes: true,
  });

  const posts = dirFiles
    .map((file) => {
      if (!file.name.endsWith('.mdx')) return;

      const fileContent = fs.readFileSync(
        path.join(process.cwd(), 'pages', 'blog', file.name),
        'utf-8'
      );
      const { data, content } = matter(fileContent);

      const slug = file.name.replace(/.mdx$/, '');
      return { data, content, slug };
    })
    .filter((post) => post);

  return posts
};

export const getReadingTime = (title) => {
  const {content} = matter(fs.readFileSync(path.join(process.cwd(), 'pages', 'blog', title + '.mdx'), 'utf-8'));
  const wordsPerMinute = 200;
  const noOfWords = content.split(/\s/g).length;
  const minutes = noOfWords / wordsPerMinute;
  const readTime = Math.ceil(minutes);
  return readTime;
}

And that's <ReadingTime />

function ReadingTime({ readingTime }) {
  return <div>{readingTime}</div>;
}

export default ReadingTime;

Expected behavior

getReadTime() should normally return the read time and get passed without any issues as a prop to <ReadingTime /> and finally gets rendered.

Actual behavior

TypeError: fs__WEBPACK_IMPORTED_MODULE_0___default(...).readdirSync is not a function

<ReadingTime readTime=getReadingTime("post-1") ^ That's what I have in my mdx file

Runtime

Node v19

Package manager

npm v8

OS

Linux

Build and bundle tools

Next.js

remcohaszing commented 1 year ago

Your problem is related to Next.js, not MDX.

You are trying to use server side data in a Next.js page. To get this data, you need to use either getStaticProps or getServerSideProps.

Your MDX file:

<ReadingTime readingTime={props.readingTime} />

export function getStaticProps() {
  return {
    props: {
      readingTime: getReadingTime("post-1")
    }
  }
}
bwkam commented 1 year ago

Ah, my bad, that was so simple, thanks! 😅