hashicorp / next-mdx-remote

Load MDX content from anywhere
Mozilla Public License 2.0
2.64k stars 140 forks source link

TypeError: _jsxDEV is not a function at _createMdxContent appeared again #464

Open pacoorozco opened 3 months ago

pacoorozco commented 3 months ago

Describe the bug

After upgrading to next-mdx-remote v5.0.0 I'm getting the _jsxDEV error. It appeared before, in previous versions, and it was fixed by setting development: false in the mdxOptions. This flag is not fixing the issue now.

The MDX content is not shown in the browser, instead we can see Application error.

And this is the content of the console:

TypeError: _jsxDEV is not a function at _createMdxContent (eval at <anonymous> (http://localhost:3000/_next/static/chunks/6503-75bc193e6aec1858.js:1:7087), <anonymous>:16:16) at MDXContent (eval at <anonymous> (http://localhost:3000/_next/static/chunks/6503-75bc193e6aec1858.js:1:7087), <anonymous>:110:14) at ad (http://localhost:3000/_next/static/chunks/framework-0e8d27528ba61906.js:9:58403) at i (http://localhost:3000/_next/static/chunks/framework-0e8d27528ba61906.js:9:119368) at oO (http://localhost:3000/_next/static/chunks/framework-0e8d27528ba61906.js:9:99021) at http://localhost:3000/_next/static/chunks/framework-0e8d27528ba61906.js:9:98888 at oF (http://localhost:3000/_next/static/chunks/framework-0e8d27528ba61906.js:9:98895) at ox (http://localhost:3000/_next/static/chunks/framework-0e8d27528ba61906.js:9:95647) at oS (http://localhost:3000/_next/static/chunks/framework-0e8d27528ba61906.js:9:94202) at x (http://localhost:3000/_next/static/chunks/framework-0e8d27528ba61906.js:33:1364)

The code is this one:

import fs from 'fs';
import matter from 'gray-matter';
import { GetStaticPropsContext, InferGetStaticPropsType } from 'next';
import Link from 'next/link';
import { MDXRemote } from 'next-mdx-remote';
import { serialize } from 'next-mdx-remote/serialize';
import { Carousel } from 'react-bootstrap';

import { CallToAction } from '@/components/Layouts/CallToAction';
import { DefaultLayout } from '@/components/Layouts/DefaultLayout';
import { PageHeader } from '@/components/Layouts/PageHeader';
import { SolutionCard } from '@/components/Layouts/SolutionCard';
import { YamsImage } from '@/components/MdxComponents/YamsImage';
import { getRandomInt } from '@/libs/randomizer';
import { getAllSolutions } from '@/libs/solutions';
import styles from '@/styles/documentation.module.scss';

// List of components allowed inside the MDX files. The more you add, the more
// loading time is increased. We try to follow less is better approach.
export const allowedComponents = {
  Carousel,
  Link,
  YamsImage,
};

export default function SolutionPage({
  source,
  frontMatter,
  relatedSolutions,
}: InferGetStaticPropsType<typeof getStaticProps>) {
  return (
    <DefaultLayout
      hasBreadcrumb={false}
      title={frontMatter.title as string}
      description={frontMatter.subtitle as string}
      image={frontMatter.imgSrc as string}
      mainClassName='container-fluid p-0 m-0 overflow-hidden'
    >
      <div className='position-relative pb-8 mb-8'>
        <PageHeader
          title={frontMatter.title as string}
          subtitle={frontMatter.subtitle as string}
          size='xl'
          showBreadcrumb={true}
        />
        <div className='px-md-6 px-lg-8 position-absolute w-100 top-0 mt-8 pt-7'>
          <YamsImage
            imageId={frontMatter.imgSrc as string}
            width='100%'
            height='480px'
            imgAlt=''
            className='pt-6'
            style={{
              objectFit: 'cover',
              maxHeight: '496px',
            }}
          />
        </div>
      </div>
      <div className='py-5 px-4 row justify-content-center'>
        <div
          data-testid='mdx-content'
          className={styles.mdx + ' pt-7 col-12 col-md-6 index-content'}
          style={{ minHeight: 'min-content' }}
        >
          <MDXRemote {...source} components={allowedComponents} />
        </div>
      </div>
      <div className='bg-light px-md-6 px-lg-8 justify-content-center'>
        <span className='d-flex w-100 justify-content-center pt-6'>
          <p className='fs-4 fw-bold text-primary-dark'>
            Explore other solutions
          </p>
        </span>
        <div className='row mt-n5 pb-6'>
          {relatedSolutions.map((solution) => {
            return (
              <SolutionCard
                key={solution.slug}
                title={solution.title}
                description={solution.subtitle ?? ''}
                href={`/solutions/${solution.slug}`}
                imgSrc={solution.imgSrc ?? ''}
              />
            );
          })}
        </div>
      </div>
      <CallToAction
        title='See YAMS in action'
        linkName='Go to demo'
        href='/demo'
        showContact={true}
        bgColorClass='success-light'
      />
    </DefaultLayout>
  );
}

export const getStaticPaths = async () => {
  const allSolutions = await getAllSolutions();

  // Get the paths we want to pre-render based on the existing MDX documents.
  const paths = allSolutions.map((solution) => ({
    params: { slug: solution.slug },
  }));

  return { paths, fallback: false };
};

export const getStaticProps = async (
  context: GetStaticPropsContext<{
    slug: string;
  }>,
) => {
  const allSolutions = await getAllSolutions();

  // Extract the slug parameter from the context. The non-null assertion (!) is used here to explicitly tell TypeScript
  // that we're confident that params is not undefined at this point in the code
  const { slug } = context.params!;

  const filename = allSolutions.find((item) => item.slug === slug)!.filename;
  const source = fs.readFileSync(filename, 'utf8');

  const { content, data } = matter(source);

  const mdxSource = await serialize(content, {
    mdxOptions: {
      remarkPlugins: [],
      rehypePlugins: [],
      development: false,
    },
  });

  // Get MAX_RELATES_SOLUTIONS solutions randomly, excluding the current one, to be shown as related content.
  const MAX_RELATED_SOLUTIONS = 2;
  const relatedSolutions = allSolutions
    .filter((solution) => solution.slug !== slug)
    .sort(() => 0.5 - getRandomInt(1))
    .slice(0, MAX_RELATED_SOLUTIONS);

  return {
    props: {
      source: mdxSource,
      frontMatter: data,
      relatedSolutions: relatedSolutions,
    },
  };
};

And I'm using next-mdx-remote@5.0.0 and next@14.2.3.

Reproduction

TypeError: _jsxDEV is not a function at _createMdxContent

next-mdx-remote version

v5.0.0

dstaley commented 3 months ago

@pacoorozco Thank you for reporting this! In order for us to look into it we need a minimal reproduction as either a public repo or CodeSandbox. That will help us track down what's actually causing this issue, as the code you've provided is not sufficient to determine the cause.

pacoorozco commented 3 months ago

Unfortunately I can't provide access to my repo (It's a GHES one). I'm going to try to create a public one with the relevant code.