javascriptnext.jsmdxjsnext.js14

Next.js attempts to parse MDX files as plain JavaScript


I'm building a website using Next.js with (local) MDX files for content. Whenever I add a .MDX file to my source tree and try to navigate to it, Next.js throws a parsing error either after '#' signs (# Heading), the front-matter, or JSX content. It simply attempts to interpret the file as plain JavaScript and fails.

I'm using Next.js version 14.0.4 and have installed the following dependencies: @next/mdx @mdx-js/loader @mdx-js/react @types/mdx gray-matter

"@mdx-js/loader": "^3.0.0",
"@mdx-js/react": "^3.0.0",
"@next/mdx": "^14.0.4",
"@types/mdx": "^2.0.10",
"gray-matter": "^4.0.3",

Here's my next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
    pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
    reactStrictMode: true,
}

module.exports = nextConfig

This is the file I'm trying to parse:

---
Title: Test Post
---

# This is just a test post

Hello!

The error messages I get look like this:

Module parse failed: Assigning to rvalue (1:2)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

I've installed the MDX loader as per the Next.js docs. I have also tried the following next.config.js, but the errors remained:

/** @type {import('next').NextConfig} */
const nextConfig = {
    pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
    webpack: (config, {defaultLoaders}) => {
        config.module.rules.push({
            test: '/\.mdx$/',
            use: [
                defaultLoaders.babel, {
                    loader: '@mdx-js/loader'
                }
            ]
        });
        return config;
    }
}

module.exports = nextConfig

Solution

  • I've figured it out, the issue was the config file. I wasn't importing withMDX from the @next/mdx package and wrapping the config object in it.

    Here's the corrected version:

    const withMDX = require('@next/mdx')();
    
    /** @type {import('next').NextConfig} */
    const nextConfig = {
        pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
        reactStrictMode: true,
    }
    
    module.exports = withMDX(nextConfig);
    

    Note that it doesn't work without the () at the end of the require statement.