MDX+Redwood+Vite (now with a workaround for Jest)
@mdx-js/rollup plugin
Install the plugin at the Redwood project root (not under the web workspace) with yarn add @mdx-js/rollup
In theory you should be able to import the plugin and add it to vite.config.ts
plugins array. In theory … In practice, you’ll run into a CSJ vs ESM module incompatibility issue. There are 2 ways resolve this.
-
The first involves adding
"types: "module"
toweb/package.json
. -
The second involves using dynamic import for the @mdx-js/plugin.
I’ve opted for the 2nd option as its effect is localized to just vite.config.ts. Modify vite.config.ts
the following way:
// const viteConfig: UserConfig = {
// plugins: [redwood()],
// }
// export default defineConfig(viteConfig)
export default defineConfig(async () => {
const mdx = await import('@mdx-js/rollup')
const viteConfig: UserConfig = {
plugins: [redwood(), mdx.default()],
}
return viteConfig
})
After this, you should be able to define an MDX component file like this:
web/src/components/Sample/Sample.mdx
# Hello World
This is an mdx example
And import it like this from another TSX or JSX file and use it like any other React component.
import Sample from 'src/components/Sample/Sample.mdx'
... <Sample /> ...
Source: MDX v2 not working · Issue #44 · brillout/vite-plugin-mdx · GitHub
Fix type errors in vscode
After the above, the MDX sample component should render. However, you’ll see the error Cannot find module 'Sample.mdx' or its corresponding type declarations
in vsCode
- Add the mdx types package
yarn workspace web add @types/mdx -D
- Declare types by creating
mdx.d.ts
underweb/types
with this content
declare module '*.mdx' {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let MDXComponent: (props: any) => JSX.Element
export default MDXComponent
}
- Reference the above declaration in tsconfig.json by adding the “mdx” to the list of types in compilerOptions
{
"compilerOptions": {
...
"types": [..., "mdx"]
},
...
}
Source: Fix typescript error for mdx files in React
Fix jest error
At this point, Jest tests for components that import mdx content will fail. Setting up actual MDX rendering is a bit convoluted for Jest. For now, I’m settling for just rendering the MDX content as null. This should keep Jest quiet.
Create the file /web/transformers/jest-return-null.js
const mdx = require('@mdx-js/mdx')
const transformer = {
//eslint-disable-next-line no-unused-vars
process: function (sourceText, sourcePath, options) {
return {
code: 'module.exports = () => null',
}
},
}
module.exports = transformer
Then add it to web/jest.config.js
const config = {
...
transform: {
'^.+\\.mdx$': '<rootDir>/web/transformers/jest-return-null.js',
},
}
All good now. Sort of.