reactjswebpackcreate-react-appbabel-loader

import "!babel-loader!mdx-loader!foo.mdx" not working with react-scripts@5.0.0


Trying to upgrade an existing React project from react-scripts@4 to @5.0.0 fails for importing transpiled MDX sources.

/* eslint import/no-webpack-loader-syntax: off */
import AboutMDX from "!babel-loader!mdx-loader!./About.mdx"

AboutMDX does not receive an MDXComponent but instead now as of react-scripts 5 end up with a string which is the path name of the transpiled javascript source code file. How can I fix this change in behavior to correctly import the MDXComponent?


Solution

  • This has been an od(d)ysee because the whole MDX2+CRA5+remark/rehype ecosystem is prone to breakage in my experience. While MDX documents to use CRACO7 with CRA5, the MDX project when kindly asked points fingers to CRACO and wasn't helpful to me in getting me over ES modules and CSJ hurdles in order to finally get the pieces to work. While the following now works for me (at the moment) I don't know how robust this set up actually is.

        "@mdx-js/loader": "^2.2.1",
        "@mdx-js/mdx": "^2.2.1",
        "@mdx-js/react": "^2.2.1",
        "@types/mdx": "^2.0.3",
    
        "@craco/craco": "^7.0.0",
        "@craco/types": "^7.0.0",
    
    const { addAfterLoader, loaderByName } = require('@craco/craco')
    
    module.exports = async (env) => {
        const remarkGfm = (await import('remark-gfm')).default
        const remarkImages = (await import('remark-images')).default
        const remarkTextr = (await import('remark-textr')).default
        const rehypeSlug = (await import('rehype-slug')).default
        const textrTypoApos = (await import('typographic-apostrophes')).default
        const textrTypoQuotes = (await import('typographic-quotes')).default
        const textrTypoPossPluralsApos = (await import('typographic-apostrophes-for-possessive-plurals')).default
        const textrTypoEllipses = (await import('typographic-ellipses')).default
        const textrTypoEmDashes = (await import('typographic-em-dashes')).default
        const textrTypoEnDashes = (await import('typographic-en-dashes')).default
    
        return {
            webpack: {
                configure: (webpackConfig) => {
                    addAfterLoader(webpackConfig, loaderByName('babel-loader'), {
                        test: /\.(md|mdx)$/,
                        loader: require.resolve('@mdx-js/loader'),
                        /** @type {import('@mdx-js/loader').Options} */
                        options: {
                            remarkPlugins: [
                                remarkGfm,
                                remarkImages,
                                [remarkTextr, {
                                    plugins: [
                                        textrTypoApos,
                                        textrTypoQuotes,
                                        textrTypoPossPluralsApos,
                                        textrTypoEllipses,
                                        // textrTypoEmDashes,
                                        textrTypoEnDashes,
                                    ],
                                    options: {
                                        locale: 'en-us'
                                    }
                                }],
                            ],
                            rehypePlugins: [
                                rehypeSlug,
                            ],
                        }
                    })
                    return webpackConfig
                }
            }
        }
    }