kentcdodds / mdx-bundler

🦤 Give me MDX/TSX strings and I'll give you back a component you can render. Supports imports!
MIT License
1.79k stars 75 forks source link

error when using styled-components in imported components #48

Closed souporserious closed 3 years ago

souporserious commented 3 years ago

What you did:

Import a component that uses styled-cmponents:

import { Counter } from './components/Counter';

# Counter Example

<Counter />
import * as React from 'react';
import styled from 'styled-components';

const StyledContainer = styled.div`
  display: flex;
  background-color: orange;
`;

export function Counter() {
  const [count, setCount] = React.useState(0);
  return (
    <StyledContainer>
      {count} <button onClick={() => setCount(count + 1)}>Increment</button>
    </StyledContainer>
  );
}

What happened:

Errors seemingly about styled-components, other third-party libraries all seem to work fine:

image

Reproduction repository:

https://github.com/souporserious/mdx-bundler-and-styled-components

Problem description:

This is in the context of a NextJS app that reaches into another directory outside of the app and pulls all of the MDX files from it. This works without styled-components, but when it's added, I get the error above.

This is my getStaticProps function responsible for fetching the MDX files:

export const getStaticProps: GetStaticProps = async ({ params }) => {
  const filePaths = await glob([
    path.resolve(__dirname, '../../../../../vapor/src/**/*.mdx'),
  ]);
  const filePath = filePaths.find((filePath) => {
    const extension = path.extname(filePath);
    const name = path
      .basename(filePath, extension)
      .split('.stories')[0];
    return name.toLowerCase().replace(/\s/g, '-') === params.slug;
  });
  const contents = await fs.readFile(path.resolve(filePath), 'utf-8');
  const { code, frontmatter } = await bundleMDX(contents, {
    cwd: path.dirname(filePath),
  });
  return {
    props: {
      code,
      frontmatter,
    },
  };
};
Arcath commented 3 years ago

Looks like esbuild needs to be told to build for Node.

You can set the platform using the esbuildOptions parameter in bundleMdx like so:

const { code, frontmatter } = await bundleMDX(contents, {
  cwd: path.dirname(filePath),
  esbuildOptions: (options) => {
    options.platform = 'node'

    return options
  }
})

This got it working on your demo repository for me.

souporserious commented 3 years ago

@Arcath that was it! 🎉 Thank you so much for looking into this, I appreciate your help!