Blog / MDX 2
Note: V2 is around the corner. This website is for that. It hasn’t been released yet. But you can try out the RC. You can be of great help by reading through these docs and letting us know what’s confusing or wrong or other suggestions you have. See § Support for where to ask questions and § Contribute for how to help.
Note: Info on how to migrate is available in our Version 2 migration guide.
Version 2 of MDX was released after years of hard work, and has many improvements. Here are the highlights:
{2 * Math.PI}
into 6.283185307179586@mdx-js/mdx
is more than three times as small (250% smaller)It’s been 4 years since this project was announced. 2½ since we released our stable version 1. We’re proud to finally release v2! Let’s dive in!
We’ve spent a lot of time thinking and trying out different ways to improve the format. Originally, the format was very close to how markdown, and HTML in markdown, works. We found that the old behavior often yielded unexpected results. In version 2, we shift the format a little bit closer to how JS(X) works.
Take for example this MDX file:
<div>*hi*?</div>
<div>
# hi?
</div>
<main>
<div>
# hi?
</div>
</main>
In version 1, that was equivalent to the following JSX:
<>
<div>*hi*?</div>
<div>
# hi?
</div>
<main>
<div>
<pre><code># hi?</code></pre>
</div>
</main>
</>
In version 2, it’s equivalent to the following JSX:
<>
<div><em>hi</em>?</div>
<div>
<h1>hi?</h1>
</div>
<main>
<div>
<h1>hi?</h1>
</div>
</main>
</>
We believe it’s more intuitive that markdown “inlines” such as emphasis can form between tags on the same line (first <div>
), “blocks” such as headings can form if they’re on their own line (second <div>
), and indentation is allowed rather than forming code (third <div>
).
We also added support for JavaScript expressions, take for example:
export const authors = [
{name: 'Jane', email: 'hi@jane.com'},
{name: 'John', twitter: '@john2002'}
]
export const published = new Date('2021-11-01')
Written by: {new Intl.ListFormat('en').format(authors.map(d => d.name))}.
Published on: {new Intl.DateTimeFormat('en', {dateStyle: 'long'}).format(published)}.
<>
<p>Written by: Jane and John.</p>
<p>Published on: November 1, 2021.</p>
</>
As the format moves a little further from markdown towards JSX, we’ve added support for loading “normal” markdown without our syntax extensions. If you’re using our bundler integration @mdx-js/loader
(or @mdx-js/rollup
, @mdx-js/esbuild
, or @mdx-js/node-loader
, see next section), then that’ll just work: import readme.mdx
and it’s seen as the MDX format, import readme.md
and it’s seen as markdown, based on their extensions.
The MDX format is described in § What is MDX?
When we started out, Babel, webpack, and React were ubiquitous in the JavaScript ecosystem and we built MDX on them. For version 2, we worked hard to make them optional. They’re no longer required and MDX can more easily be used with other tools.
On the bundler side, we’ve added new integrations: @mdx-js/esbuild
for esbuild (an extremely fast bundler) and @mdx-js/rollup
for Rollup (a bundler that’s also used in Vite and WMR). You can even import MDX files directly in Node.js with our new @mdx-js/node-loader
.
On the runtime side, we can now compile JSX away to normal JavaScript and no longer need framework-specific code to glue them together with MDX. Now any JSX runtime, whether classic or automatic, is supported. This means MDX can be used with React, Preact, Vue, Emotion, Theme UI, Ink, you name it, plus anything that’s yet to be invented!
See § Getting started for a quick start but also in-depth info on how to integrate MDX with many different tools.
To make the syntax of the MDX format better and to allow new integrations and arbitrary JSX runtimes, we’ve rewritten almost everything. Part of that effort was micromark, which is another story, but it means we’re fully CommonMark (and optionally GFM) compliant, while also understanding more about MDX files.
Now we can throw an early error when there’s a typo and point to exactly where it happened, instead of a later bundler like webpack complaining about an error in an intermediate, unrecognizable, and broken string of JavaScript. It also means that we have a new AST which describes the MDX syntax in more detail — we even expose the embedded JavaScript. This detailed AST allows plugins to enhance MDX in powerful new ways. It also helped solve edge cases where MDX would previously crash. And it let us drop Babel.
This new architecture results in 25% faster compilation, generated code that runs twice as fast (100% faster), and that the bundle size of @mdx-js/mdx
is more than three times as small (250% smaller).
See ¶ Architecture in @mdx-js/mdx
for more on how our compiler works. See § Extending MDX for several plugins that use the new tree to enhance MDX, how to use them and other plugins, and how to create plugins.
All @mdx-js/*
packages are now fully typed with TypeScript through JSDoc comments. That means our APIs are exposed as TypeScript types but also that our projects are type safe internally.
We’ve published @types/mdx
, a types-only package that can be used with any (community) integration. You can use it, if you’re importing MDX files, to type those imported components.
See ¶ TypeScript in § Getting started for more on how to use configure TypeScript.
MDX is used and liked a lot. Before version 1 we had amassed a total of 2.5m downloads. Now we hit that number every week. Our core compiler @mdx-js/mdx
is used in 61k projects. Our GitHub repo has 11.6k stars.
Many people help, often with docs. 85 contributors committed to our repo since version 1. We’re grateful for these contributions and all those individual insights, but over the years it did result in some inconsistencies and duplicated content.
For version 2, we rewrote our docs from beginning to end to tell a consistent story for new users, folks wanting to do complex AST and compiler stuff, and anyone in between.
We also made a new website. It’s built on MDX of course, unified itself, and React Server Components (RSC). While we have to dogfood the former two as they’re projects we maintain, and the latter is extremely experimental, we think compiling things ahead of time and betting on hybrid models, compared to completely server-side sites or completely client-side apps, is the smart choice for us and the web’s future.
Our new site is heavily optimized and fast, gorgeous (subjective but hey), has rich metadata, and scores very well in performance and accessibility review tools such as Lighthouse and axe.
See § Contribute for more on how to help.
When you’re ready to migrate, please see the Version 2 migration guide.
Important: To do! We’ll do this when v2 actually hits. So there’s still time to get your name here 😉
We’d like to say thanks to all our contributors and our happy users. Special thanks to ... and anyone we may have forgotten.