{
",id:"bad-usage-of-",level:4},{value:"Bad usage of <
",id:"bad-usage-of--1",level:4},{value:"Bad usage of GFM Autolink",id:"bad-usage-of-gfm-autolink",level:4},{value:"Lower-case MDXComponent mapping",id:"lower-case-mdxcomponent-mapping",level:4},{value:"Unintended extra paragraphs",id:"unintended-extra-paragraphs",level:4},{value:"Unintended usage of directives",id:"unintended-usage-of-directives",level:4},{value:"Unsupported indented code blocks",id:"unsupported-indented-code-blocks",level:4},{value:"MDX plugins",id:"mdx-plugins",level:3},{value:"Other breaking changes",id:"other-breaking-changes",level:2},{value:"Node.js 18.0",id:"nodejs-180",level:3},{value:"React 18.0",id:"react-180",level:3},{value:"TypeScript 5.0",id:"typescript-50",level:3},{value:"TypeScript base config",id:"typescript-base-config",level:3},{value:"Admonition warning",id:"admonition-warning",level:3},{value:"Versioned sidebars",id:"versioned-sidebars",level:3},{value:"Try Docusaurus v3 today",id:"try-docusaurus-v3-today",level:2},{value:"Ask for help",id:"ask-for-help",level:2},{value:"Conclusion",id:"conclusion",level:2}];function l(e){let n={a:"a",admonition:"admonition",blockquote:"blockquote",code:"code",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.a)(),...e.components},{Details:r}=n;return r||function(e,n){throw Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.admonition,{type:"warning",children:(0,o.jsxs)(n.p,{children:["This blog post was written when Docusaurus v3 was in beta. There are some changes in dependency versions and upgrade steps you should be aware of if upgrading to Docusaurus v3 current stable releases. Use the ",(0,o.jsx)(n.a,{href:"https://docusaurus.io/docs/next/migration/v3",children:"upgrade guide"})," for the most up-to-date migration steps."]})}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Docusaurus v3"})," is now ",(0,o.jsx)(n.a,{href:"https://github.com/facebook/docusaurus/discussions/9312",children:(0,o.jsx)(n.strong,{children:"in beta"})})," and the official release is around the corner. This is the perfect time to start ",(0,o.jsx)(n.strong,{children:"preparing your site"})," for this new major version."]}),"\n",(0,o.jsxs)(n.p,{children:["Docusaurus v3 comes with a few ",(0,o.jsx)(n.strong,{children:"breaking changes"}),", many of which can be ",(0,o.jsx)(n.strong,{children:"handled today under Docusaurus v2"}),". Preparing your site ahead of time can be done incrementally, and will make it easier to upgrade to v3."]}),"\n",(0,o.jsxs)(n.p,{children:["The main breaking change is the upgrade from MDX v1 to MDX v3. Read the ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/blog/v2/",children:(0,o.jsx)(n.strong,{children:"MDX v2"})})," and ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/blog/v3/",children:(0,o.jsx)(n.strong,{children:"MDX v3"})})," release notes for details. MDX will now compile your Markdown content ",(0,o.jsx)(n.strong,{children:"more strictly"})," and with ",(0,o.jsx)(n.strong,{children:"subtle differences"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"This article will mostly focus on how to prepare your content for this new MDX version, and will also list a few other breaking changes that you can handle today."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Preparing your site for Docusaurus v3 - social card",src:s(32007).Z+"",width:"1040",height:"546"})}),"\n",(0,o.jsx)(n.admonition,{type:"warning",children:(0,o.jsxs)(n.p,{children:["This article mentions most Docusaurus v3 breaking changes, but is not exhaustive. Read the ",(0,o.jsx)(n.a,{href:"https://github.com/facebook/docusaurus/discussions/9312",children:"v3.0.0-beta.0 release notes"})," for an exhaustive list."]})}),"\n",(0,o.jsxs)(n.admonition,{title:"Don't be afraid",type:"tip",children:[(0,o.jsx)(n.p,{children:"There's a lot of content in this blog post, but many Docusaurus v2 sites can upgrade with very few changes."}),(0,o.jsxs)(n.p,{children:["If your site is relatively small, with only a few customizations, you can probably ",(0,o.jsx)(n.a,{href:"#try-docusaurus-v3-today",children:"upgrade to Docusaurus v3"})," immediately."]})]}),"\n",(0,o.jsx)(n.h2,{id:"preparatory-work",children:"Preparatory work"}),"\n",(0,o.jsxs)(n.p,{children:["Before preparing for the Docusaurus v3 upgrade, we recommend upgrading to the latest ",(0,o.jsx)(n.a,{href:"/versions",children:"Docusaurus v2 version"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Depending on the complexity of your site, it may be a good idea to adopt the ",(0,o.jsx)(n.a,{href:"/blog/upgrading-frontend-dependencies-with-confidence-using-visual-regression-testing",children:"visual regression testing workflow"})," that we recently presented. It could help you catch unexpected visual side effects occurring during the Docusaurus v3 upgrade."]}),"\n",(0,o.jsxs)(n.p,{children:["We also recommend using the ",(0,o.jsx)(n.code,{children:".mdx"})," extension whenever you use JSX, ",(0,o.jsx)(n.code,{children:"import"}),", or ",(0,o.jsx)(n.code,{children:"export"})," (i.e. MDX features) inside a Markdown file. It is semantically more correct and improves compatibility with external tools (IDEs, formatters, linters, etc.). In future versions of Docusaurus, ",(0,o.jsx)(n.code,{children:".md"})," files will be parsed as standard ",(0,o.jsx)(n.a,{href:"https://commonmark.org/",children:"CommonMark"}),", which does not support these features. In Docusaurus v3, ",(0,o.jsx)(n.code,{children:".md"})," files keep being compiled as MDX files, but it will be possible to ",(0,o.jsx)(n.a,{href:"https://github.com/facebook/docusaurus/issues/3018",children:"opt-in for CommonMark"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"preparing-content-for-mdx-v3",children:"Preparing content for MDX v3"}),"\n",(0,o.jsxs)(n.p,{children:["MDX is a major dependency of Docusaurus responsible for compiling your ",(0,o.jsx)(n.code,{children:".md"})," and ",(0,o.jsx)(n.code,{children:".mdx"})," files to React components."]}),"\n",(0,o.jsxs)(n.p,{children:["MDX v3 is much better, but also comes with changes that probably require you to refactor your content a bit. MDX v3 is stricter, and some components that compiled fine under v1 might now fail to compile under v3, most likely because of ",(0,o.jsx)(n.code,{children:"{"})," and ",(0,o.jsx)(n.code,{children:"<"})," characters."]}),"\n",(0,o.jsxs)(n.p,{children:["Upgrading MDX comes with all the breaking changes documented on the ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/blog/v2/",children:"MDX v2"})," and ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/blog/v3/",children:"MDX v3"})," release blog posts. Most breaking changes come from MDX v2. The ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/migrating/v2/",children:"MDX v2 migration guide"})," has a section on how to ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/migrating/v2/#update-mdx-files",children:"update MDX files"})," that will be particularly relevant to us. Also make sure to read the ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/docs/troubleshooting-mdx/",children:"Troubleshooting MDX"})," page that can help you interpret common MDX error messages."]}),"\n",(0,o.jsxs)(n.p,{children:["Make sure to also read our updated ",(0,o.jsx)(n.a,{href:"/docs/markdown-features/react",children:(0,o.jsx)(n.strong,{children:"MDX and React"})})," documentation page."]}),"\n",(0,o.jsx)(n.admonition,{title:"Ask for help",type:"tip",children:(0,o.jsxs)(n.p,{children:["We have a dedicated ",(0,o.jsx)(n.a,{href:"https://github.com/facebook/docusaurus/discussions/9053",children:"MDX v3 - Upgrade Support"})," discussion."]})}),"\n",(0,o.jsx)(n.h3,{id:"using-the-mdx-playground",children:"Using the MDX playground"}),"\n",(0,o.jsxs)(n.p,{children:["The MDX playground is your new best friend. It permits to understand how your content is ",(0,o.jsx)(n.strong,{children:"compiled to React components"}),", and troubleshoot compilation or rendering issues in isolation."]}),"\n",(0,o.jsx)(n.p,{children:"Each MDX version comes with its own playground:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://mdxjs.com/playground/",children:"MDX playground - current version"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://mdx-git-renovate-babel-monorepo-mdx.vercel.app/playground/",children:"MDX playground - v1"})}),"\n"]}),"\n",(0,o.jsxs)(r,{children:[(0,o.jsx)("summary",{children:"Configuring the MDX playground options for Docusaurus"}),(0,o.jsxs)(n.p,{children:["To obtain a compilation behavior similar to what Docusaurus v2 uses, please turn on these options on the ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/playground/",children:"MDX playground"}),":"]}),(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Use ",(0,o.jsx)(n.code,{children:"MDX"})]}),"\n",(0,o.jsxs)(n.li,{children:["Use ",(0,o.jsx)(n.code,{children:"remark-gfm"})]}),"\n",(0,o.jsxs)(n.li,{children:["Use ",(0,o.jsx)(n.code,{children:"remark-directive"})]}),"\n"]}),(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Screenshot of the MDX playground's options panel, with only the "Use MDX", "Use remark-gfm", and "Use remark-directive" options checked",src:s(51476).Z+"",width:"1968",height:"1316"})})]}),"\n",(0,o.jsx)(n.p,{children:"Using the two MDX playgrounds side-by-side, you will soon notice that some content is compiled differently or fails to compile in v3."}),"\n",(0,o.jsx)(n.admonition,{title:"Making your content future-proof",type:"tip",children:(0,o.jsxs)(n.p,{children:["The goal will be to refactor your problematic content so that it ",(0,o.jsx)(n.strong,{children:"works fine with both versions of MDX"}),". This way, when you upgrade to Docusaurus v3, this content will already work out-of-the-box."]})}),"\n",(0,o.jsx)(n.h3,{id:"using-the-mdx-checker-cli",children:"Using the MDX checker CLI"}),"\n",(0,o.jsxs)(n.p,{children:["We provide a ",(0,o.jsx)(n.a,{href:"https://github.com/slorber/docusaurus-mdx-checker",children:"docusaurus-mdx-checker"})," CLI that permits to easily spot problematic content. Run this command today on your Docusaurus v2 site to obtain a list of files that will fail to compile under MDX v3."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"npx docusaurus-mdx-checker\n"})}),"\n",(0,o.jsx)(n.p,{children:"For each compilation issue, the CLI will log the file path and a line number to look at."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Screenshot of the terminal showing an example MDX checker CLI output, with a few error messages",src:s(85345).Z+"",width:"1161",height:"417"})}),"\n",(0,o.jsx)(n.admonition,{type:"tip",children:(0,o.jsx)(n.p,{children:"Use this CLI to estimate of how much work will be required to make your content compatible with MDX v3."})}),"\n",(0,o.jsxs)(n.admonition,{type:"warning",children:[(0,o.jsx)(n.p,{children:"This CLI is a best effort, and will only report compilation errors."}),(0,o.jsxs)(n.p,{children:["It will not report subtle compilation changes that do not produce errors but can affect how your content is displayed. To catch these problems, we recommend using ",(0,o.jsx)(n.a,{href:"/blog/upgrading-frontend-dependencies-with-confidence-using-visual-regression-testing",children:"visual regression tests"}),"."]})]}),"\n",(0,o.jsx)(n.h3,{id:"common-mdx-problems",children:"Common MDX problems"}),"\n",(0,o.jsx)(n.p,{children:"We upgraded a few Docusaurus sites to Docusaurus v3 and MDX v3:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://github.com/facebook/docusaurus/pull/8288",children:"Docusaurus PR"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://github.com/facebook/react-native-website/pull/3780",children:"React-Native PR"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://github.com/jestjs/jest/pull/14463",children:"Jest PR"})}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"These upgrades permitted us to aggregate the most common content problems, and document how to best handle them."}),"\n",(0,o.jsxs)(n.h4,{id:"bad-usage-of-",children:["Bad usage of ",(0,o.jsx)(n.code,{children:"{"})]}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"{"})," character is used for opening ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/docs/what-is-mdx/#expressions",children:"JavaScript expressions"}),". MDX will now fail if what you put inside ",(0,o.jsx)(n.code,{children:"{expression}"})," is not a valid expression."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-md",metastring:'title="example.md"',children:"The object shape looks like {username: string, age: number}\n"})}),"\n",(0,o.jsx)(n.admonition,{title:"Error message",type:"danger",children:(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsx)(n.p,{children:"Could not parse expression with acorn: Unexpected content after expression"}),"\n"]})}),"\n",(0,o.jsxs)(n.admonition,{title:"How to prepare",type:"tip",children:[(0,o.jsx)(n.p,{children:"Available options to fix this error:"}),(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Use inline code: ",(0,o.jsx)(n.code,{children:"{username: string, age: number}"})]}),"\n",(0,o.jsxs)(n.li,{children:["Use the HTML code: ",(0,o.jsx)(n.code,{children:"{"})]}),"\n",(0,o.jsxs)(n.li,{children:["Escape it: ",(0,o.jsx)(n.code,{children:"\\{"})]}),"\n"]})]}),"\n",(0,o.jsxs)(n.h4,{id:"bad-usage-of--1",children:["Bad usage of ",(0,o.jsx)(n.code,{children:"<"})]}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"<"})," character is used for opening ",(0,o.jsx)(n.a,{href:"https://mdxjs.com/docs/what-is-mdx/#jsx",children:"JSX tags"}),". MDX will now fail if it thinks your JSX is invalid."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-md",metastring:'title="example.md"',children:'Use Android version <5\n\nYou can use a generic type like Array"})," tags."]}),"\n",(0,o.jsxs)(n.admonition,{title:"visual difference",type:"danger",children:[(0,o.jsx)(n.p,{children:"See how this content is rendered differently by MDX v1 and v3."}),(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-md",metastring:'title="example.md"',children:"
Some Markdown content
"})," tag, refactor content on a case by case basis to use a single-line JSX tag."]}),(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-diff",children:' \n-