Docusaurus v3 is now in beta and the official release is around the corner. This is the perfect time to start preparing your site for this new major version.
Docusaurus v3 comes with a few breaking changes, many of which can be handled today under Docusaurus v2. Preparing your site ahead of time can be done incrementally, and will make it easier to upgrade to v3.
The main breaking change is the upgrade from MDX v1 to MDX v3. Read the MDX v2 and MDX v3 release notes for details. MDX will now compile your Markdown content more strictly and with subtle differences.
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.
This article mentions most Docusaurus v3 breaking changes, but is not exhaustive. Read the v3.0.0-beta.0 release notes for an exhaustive list.
There's a lot of content in this blog post, but many Docusaurus v2 sites can upgrade with very few changes.
If your site is relatively small, with only a few customizations, you can probably upgrade to Docusaurus v3 immediately.
Preparatory workβ
Before preparing for the Docusaurus v3 upgrade, we recommend upgrading to the latest Docusaurus v2 version.
Depending on the complexity of your site, it may be a good idea to adopt the visual regression testing workflow that we recently presented. It could help you catch unexpected visual side effects occurring during the Docusaurus v3 upgrade.
We also recommend using the .mdx
extension whenever you use JSX, import
, or 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, .md
files will be parsed as standard CommonMark, which does not support these features. In Docusaurus v3, .md
files keep being compiled as MDX files, but it will be possible to opt-in for CommonMark.
Preparing content for MDX v3β
MDX is a major dependency of Docusaurus responsible for compiling your .md
and .mdx
files to React components.
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 {
and <
characters.
Upgrading MDX comes with all the breaking changes documented on the MDX v2 and MDX v3 release blog posts. Most breaking changes come from MDX v2. The MDX v2 migration guide has a section on how to update MDX files that will be particularly relevant to us. Also make sure to read the Troubleshooting MDX page that can help you interpret common MDX error messages.
Make sure to also read our updated MDX and React documentation page.
We have a dedicated MDX v3 - Upgrade Support discussion.
Using the MDX playgroundβ
The MDX playground is your new best friend. It permits to understand how your content is compiled to React components, and troubleshoot compilation or rendering issues in isolation.
Each MDX version comes with its own playground:
Configuring the MDX playground options for Docusaurus
To obtain a compilation behavior similar to what Docusaurus v2 uses, please turn on these options on the MDX playground:
- Use
MDX
- Use
remark-gfm
- Use
remark-directive
Using the two MDX playgrounds side-by-side, you will soon notice that some content is compiled differently or fails to compile in v3.
The goal will be to refactor your problematic content so that it works fine with both versions of MDX. This way, when you upgrade to Docusaurus v3, this content will already work out-of-the-box.
Using the MDX checker CLIβ
We provide a 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.
npx docusaurus-mdx-checker
For each compilation issue, the CLI will log the file path and a line number to look at.
Use this CLI to estimate of how much work will be required to make your content compatible with MDX v3.
This CLI is a best effort, and will only report compilation errors.
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 visual regression tests.
Common MDX problemsβ
We upgraded a few Docusaurus sites to Docusaurus v3 and MDX v3:
These upgrades permitted us to aggregate the most common content problems, and document how to best handle them.
Bad usage of {
β
The {
character is used for opening JavaScript expressions. MDX will now fail if what you put inside {expression}
is not a valid expression.
The object shape looks like {username: string, age: number}
Could not parse expression with acorn: Unexpected content after expression
Available options to fix this error:
- Use inline code:
{username: string, age: number}
- Use the HTML code:
{
- Escape it:
\{
Bad usage of <
β
The <
character is used for opening JSX tags. MDX will now fail if it thinks your JSX is invalid.
Use Android version <5
You can use a generic type like Array<T>
Follow the template "Road to <YOUR_MINOR_VERSION>"
Unexpected character
5
(U+0035) before name, expected a character that can start a name, such as a letter,$
, or_
Expected a closing tag for
<T>
(1:6-1:9) before the end ofparagraph
end-tag-mismatch mdast-util-mdx-jsx
Expected a closing tag for
<YOUR_MINOR_VERSION>
(134:19-134:39) before the end ofparagraph
Available options to fix this error:
- Use inline code:
Array<T>
- Use the HTML code:
<
or<
- Escape it:
\<
(unfortunately the\
will be displayed under MDX v1)
Bad usage of GFM Autolinkβ
Docusaurus supports GitHub Flavored Markdown (GFM), but autolink using the <link>
syntax is not supported anymore by MDX.
<sebastien@thisweekinreact.com>
<http://localhost:3000>
Unexpected character
@
(U+0040) in name, expected a name character such as letters, digits,$
, or_
; whitespace before attributes; or the end of the tag (note: to create a link in MDX, use[text](url)
)
Unexpected character
/
(U+002F) before local name, expected a character that can start a name, such as a letter,$
, or_
(note: to create a link in MDX, use[text](url)
)
Use regular Markdown links, or remove the <
and >
. MDX and GFM are able to autolink literals already.
sebastien@thisweekinreact.com
[sebastien@thisweekinreact.com](mailto:sebastien@thisweekinreact.com)
http://localhost:3000
[http://localhost:3000](http://localhost:3000)
Lower-case MDXComponent mappingβ
For users providing a custom MDXComponent
mapping, components are now "sandboxed":
- a
MDXComponent
mapping forh1
only gets used for# hi
but not for<h1>hi</h1>
- a lower-cased custom element name will not be substituted by its respective
MDXComponent
component anymore
Your MDXComponent
component mapping might not be applied as before, and your custom components might no longer be used.
For native Markdown elements, you can keep using lower-case: p
, h1
, img
, a
...
For any other element, use upper-case names.
import MDXComponents from '@theme-original/MDXComponents';
export default {
...MDXComponents,
p: (props) => <p {...props} className="my-paragraph"/>
- myElement: (props) => <div {...props} className="my-class" />,
+ MyElement: (props) => <div {...props} className="my-class" />,
};
Unintended extra paragraphsβ
In MDX, it is now possible to interleave JSX and Markdown more easily without requiring extra line breaks. Writing content on multiple lines can also produce new expected <p>
tags.
See how this content is rendered differently by MDX v1 and v3.
<div>Some **Markdown** content</div>
<div>
Some **Markdown** content
</div>
<div>Some **Markdown** content</div>
<div>Some **Markdown** content</div>
<div>Some <strong>Markdown</strong> content</div>
<div><p>Some <strong>Markdown</strong> content</p></div>
If you don't want an extra <p>
tag, refactor content on a case by case basis to use a single-line JSX tag.
<figure>
<img src="/img/myImage.png" alt="My alt" />
- <figcaption>
- My image caption
- </figcaption>
+ <figcaption>My image caption</figcaption>
</figure>
If your content contains "Markdown inlines" (**
, *
, _
, [link](/path)
), you might not be able to refactor it ahead of time, and will have to do it alongside the Docusaurus v3 upgrade.
Unintended usage of directivesβ
Docusaurus v3 now uses Markdown Directives (implemented with remark-directive) as a generic way to provide support for admonitions, and other upcoming Docusaurus features.
This is a :textDirective
::leafDirective
:::containerDirective
Container directive content
:::
Directives are parsed with the purpose of being handled by other Remark plugins. Unhandled directives will be ignored, and won't be rendered back in their original form.
The AWS re:Invent conf is great
Due to :Invent
being parsed as a text directive, this will now be rendered as:
The AWS re
conf is great
- Use the HTML code:
:
- Add a space after
:
(if it makes sense):: text
- Escape it:
\:
(unfortunately the\
will be displayed under MDX v1)
Unsupported indented code blocksβ
MDX does not transform indented text as code blocks anymore.
console.log("hello");
The upgrade does not generally produce new MDX compilation errors, but can lead to content being rendered in an unexpected way because there isn't a code block anymore.
Use the regular code block syntax instead of indentation:
```js
console.log('hello');
```
MDX pluginsβ
All the official packages (Unified, Remark, Rehype...) in the MDX ecosystem are now ES Modules only and do not support CommonJS anymore.
In practice this means that you can't do require("remark-plugin")
anymore.
Docusaurus v3 now supports ES Modules configuration files. We recommend that you migrate your config file to ES module, that enables you to import the Remark plugins easily:
import remarkPlugin from 'remark-plugin';
export default {
title: 'Docusaurus',
/* site config using remark plugins here */
};
If you want to keep using CommonJS modules, you can use dynamic imports as a workaround that enables you to import ES modules inside a CommonJS module. Fortunately, the Docusaurus config supports the usage of an async function to let you do so.
module.exports = async function () {
const myPlugin = (await import('remark-plugin')).default;
return {
// site config...
};
};
If you created custom Remark or Rehype plugins, you may need to refactor those, or eventually rewrite them completely, due to how the new AST is structured. We have created a dedicated support discussion to help plugin authors upgrade their code.
Other breaking changesβ
Apart from MDX, there are other breaking changes that you can already prepare your site for, notably major version upgrades of important dependencies.
Node.js 18.0β
Node.js 16 reached End-of-Life, and Docusaurus v3 now requires Node.js >= 18.0.
Upgrade your Docusaurus v2 site to Node.js 18 before upgrading to Docusaurus v3.
React 18.0β
Docusaurus v3 now requires React >= 18.0.
React 18 comes with its own breaking changes that should be relatively easy to handle, depending on the amount of custom React code you created for your site.
Simple Docusaurus sites that only use our official theme code without swizzling do not have anything to do.
Read the official React v18.0 and How to Upgrade to React 18, and look at your first-party React code to figure out which components might be affected this React 18 upgrade.
We recommend to particularly look for:
- Automatic batching for stateful components
- New React hydration errors reported to the console
TypeScript 5.0β
Docusaurus v3 now requires TypeScript >= 5.0.
Upgrade your Docusaurus v2 site to TypeScript 5 before upgrading to Docusaurus v3.
TypeScript base configβ
The official Docusaurus TypeScript config has been re-internalized from the external package @tsconfig/docusaurus
to our new monorepo package @docusaurus/tsconfig
.
This new package is versioned alongside all the other Docusaurus core packages, and will be used to ensure TypeScript retro-compatibility and breaking changes on major version upgrades.
The new Docusaurus v3 TypeScript config is sensibly the same as the former Docusaurus v2 TypeScript config. If you upgraded to TypeScript 5, using the Docusaurus v3 config on a v2 site is already possible:
{
"devDependencies": {
- "@tsconfig/docusaurus": "^1.0.7",
+ "@docusaurus/tsconfig": "^3.0.0-beta.0",
}
}
{
- "extends": "@tsconfig/docusaurus/tsconfig.json",
+ "extends": "@docusaurus/tsconfig",
"compilerOptions": {
"baseUrl": "."
}
}
Admonition warningβ
For historical reasons, we support an undocumented admonition :::warning
that renders with a red color.
This is a Docusaurus v2 :::warning
admonition.
However, the color and icon is historically wrong. Docusaurus v3 re-introduces :::warning
admonition officially, documents it, and fix the color and icon.
This is a Docusaurus v3 :::warning
admonition.
If you previously used the undocumented :::warning
admonition, make sure to verify for each usage if yellow is now an appropriate color. If you want to keep the red color, use :::danger
instead.
Docusaurus v3 also deprecated the :::caution
admonition. Please refactor :::caution
(yellow) to either :::warning
(yellow) or :::danger
(red).
Versioned sidebarsβ
This breaking change will only affect Docusaurus v2 early adopters who versioned their docs before v2.0.0-beta.10
(December 2021).
When creating version v1.0.0
, the sidebar file contained a prefix version-v1.0.0/
that Docusaurus v3 does not support anymore.
{
"version-v1.0.0/docs": [
"version-v1.0.0/introduction",
"version-v1.0.0/prerequisites"
]
}
Your Docusaurus v2 site is able to handle the 2 sidebar formats similarly.
You can remove the useless versioned prefix from your versioned sidebars.
{
"docs": ["introduction", "prerequisites"]
}
Try Docusaurus v3 todayβ
Docusaurus v3 is now in beta, and already used in production by React-Native, Jest, and our own website.
We think this new Docusaurus version is robust and ready to be deployed in production. It should be released officially soon, after receiving a positive feedback from early adopters of our community.
We would really appreciate it if you try upgrading and report issues on the 3.0.0-beta.0 release discussion thread.
For most sites, the upgrade should be easy. If you prepared your site ahead of time as documented here, upgrading the following dependencies should be enough:
{
"dependencies": {
- "@docusaurus/core": "2.4.3",
- "@docusaurus/preset-classic": "2.4.3",
- "@mdx-js/react": "^1.6.22",
+ "@docusaurus/core": "3.0.0-beta.0",
+ "@docusaurus/preset-classic": "3.0.0-beta.0",
+ "@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^1.3.5",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
},
"devDependencies": {
- "@docusaurus/module-type-aliases": "2.4.3"
+ "@docusaurus/module-type-aliases": "3.0.0-beta.0"
}
}
Ask for helpβ
We will be there to help you upgrade through the following support channels:
- Docusaurus v3 - Upgrade Support
- Docusaurus v3 - Discord channel #migration-v2-to-v3
- MDX v3 - Upgrade Support
- MDX v3 - Remark/Rehype Plugins Support
- MDX v3 - Discord channel #migration-mdx-v3
Alternatively, you can look for a paid Docusaurus Service Provider to execute this upgrade for you. If your site is open source, you can also ask our community for free, benevolent help.
Conclusionβ
Docusaurus v3 is ready to try, and will be released soon. This article already gives you a good idea of all the major changes required to upgrade.
The initial 3.0 release is focusing on dependency and infrastructure upgrades that will permit us to implement new exciting features. It also comes with a few useful features that we will detail in the final release notes.