docusaurus
docusaurus copied to clipboard
Migrate to React 18
Have you read the Contributing Guidelines on issues?
- [X] I have read the Contributing Guidelines on issues.
For site maintainers
Upgrading to React 18 is optional—it won't break anything, but it won't do anything either. Until Docusaurus uses the new createRoot API, the site's behavior will still be the same as that in React 17. However, you may be able to use a few React 18 niceties like useId() (which I'm personally excited about for accessibility reasons).
If your dependency management bot wants to upgrade to React 18 for you, and it doesn't cause any problems (around peer dependencies), feel free to accept it.
Motivation
Unlike React 17, React 18 contains actual API changes that may not be backward-compatible (i.e. you can't take a React 18 program and expect it to run in a project installed with React 17). Therefore, migration to React 18 can only happen along two paths:
- We migrate to React 18 by using the new
createRootAPI, and throw an early error for anyone still installed withreact@17, telling them to update their package.json.- Problem: breaks virtually every site, some sites already having a version of React in their monorepo may end up having duplicate copies, which opens a can of worms.
- We detect the version of React installed, and selectively uses
ReactDOM.renderorcreateRootbased on the version.- Problem: hacky code, slightly increases bundle size, and harder to maintain in the long run (refactoring hazards)
It is not good to move forward with either solution.
We have some preliminary work done in #7102, but it's far from being complete, and gets stalled in multiple places. The resolution is that as the 2.0 release is approaching, we'll likely stay on React 17 because the truth is, even many libraries are not fully prepared for React 18 yet! React 18 will be considered a breaking change and will come in v3.
The most urgent blocking issue is that MDX v1 doesn't declare React v18 in its peer dependencies range. Because the v1 line is effectively frozen, I believe there's no plan to fix this. Certain package managers (namely, npm v7 and pnpm) are strict about peer dependencies and will refuse to install properly if @mdx-js/react is installed alongside react@18. This will be confusing for the users, so it's another strong point why we'll delay it to v3: we'll only migrate to MDX v2 in Docusaurus v3 (#4029).
Since I don't think React 18 actually removed any API, there's not much we need to do on the code side. It's only about dependencies. Still, it would be nice if we can remove react-loadable (#3841), because it uses the deprecated componentWillMount lifecycle and prevents us from opting into StrictMode. Also, React 18 will bring support for new SSG APIs (including server-rendering Suspense), and we'll want to take the opportunity of prolonged migration time window to look into that as well.
Self-service
- [ ] I'd be willing to do some initial work on this proposal myself.
Hi,
I thought we can incrementally adopt to React 18 which give easy migration process too 😊
if (React.version.includes("18.")) {
if (process.env.NODE_ENV === "production") {
const { hydrateRoot } = require("react-dom/client");
preload(window.location.pathname).then(() => {
hydrateRoot(
document.getElementById("__docusaurus"),
<HelmetProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</HelmetProvider>
);
});
} else {
const { createRoot } = require("react-dom/client");
preload(window.location.pathname).then(() => {
const docReactRoot = createRoot(
document.getElementById("__docusaurus")
);
docReactRoot.render(
<HelmetProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</HelmetProvider>
);
});
}
} else {
const ReactDOM = require("react-dom");
const renderMethod =
process.env.NODE_ENV === "production"
? ReactDOM.hydrate
: ReactDOM.render;
preload(window.location.pathname).then(() => {
renderMethod(
<HelmetProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</HelmetProvider>,
document.getElementById("__docusaurus")
);
});
}
In above code we dynamically require the new react 18 dom lib with fallback for older versions :)
I am sorry if I made any errors/mistakes :(
@sanjaiyan-dev That falls under the realm of
Problem: hacky code, slightly increases bundle size, and harder to maintain in the long run (refactoring hazards)
I'm not really willing to maintain that code, but it's a nice path nevertheless. Let's wait till v3 is actually on the roadmap to decide what is best for us.
@sanjaiyan-dev That falls under the realm of
Problem: hacky code, slightly increases bundle size, and harder to maintain in the long run (refactoring hazards)
I'm not really willing to maintain that code, but it's a nice path nevertheless. Let's wait till v3 is actually on the roadmap to decide what is best for us.
Yh 💪🙌
So react 18 would never be supported on V2? only on the future version, Docusaurus V3?
There are some really nice features in React18. For example, ReactDOMServer (which is used on production build) 18 allows lazy loading of React components, which in turn allows write and use of custom components that show a live preview of a component and its code. Such custom components can't be written in ReactDOMServer 17 (but strangely supported on react 17. so would encounter errors on Docusaurus only on production build)
We hope to release Docusaurus v3 very quickly. According to our release doc, it should be within a few months, so you should not worry about it too much. React 18 will be a major change, so no, it will not be backported. Also, we have abstracted all the build pipeline, and we hope you could develop without caring about the underlying plumbing infra.
When can we expect the first canary release that uses React 18? Saw that you have 3.0.0-alpha.0 but it's still on React 17?
Hi! I have a problem that I think is related to this issue. I have a monorepo (turborepo) and I can't have multiple versions of react in it. (otherwise react breaks) I'm trying to change the docusaurus project's react dependency to 18, but npm install fails with:
peer react@"^16.13.1 || ^17.0.0" from @mdx-js/[email protected]
I noticed that next-auth has a similar project structure and is successfully using react 18 in the docusaurus project.
I tried to replicate it on my project, but wasn't successful. Does someone understand how they did it? Is there anyway I can work around this problem?
Thank you in advance.
Hi! I have a problem that I think is related to this issue. I have a monorepo (turborepo) and I can't have multiple versions of react in it. (otherwise react breaks) I'm trying to change the docusaurus project's react dependency to 18, but npm install fails with:
peer react@"^16.13.1 || ^17.0.0" from @mdx-js/[email protected]I noticed that
next-authhas a similar project structure and is successfully using react 18 in the docusaurus project.I tried to replicate it on my project, but wasn't successful. Does someone understand how they did it? Is there anyway I can work around this problem?
Thank you in advance.
Just disable strict peer dependencies. If you're on pnpm, create a .npmrc and put strict-peer-dependencies=false in it
@juliusmarminge thanks for the guidance!
I was able to make it work with the command npm i --legacy-peer-deps now that the lock file has the structure, I'm able to instal with only npm i.
Would also love to know if there's an updated timeline somewhere for support. Wasn't able to come up with branches / tags to look at. Would be happy to play the guinea pig here! (we're actually "dependent" on React 18, because we'd love to integrate https://github.com/pacocoursey/cmdk with our docs)
Is a contribution needed here to keep this item moving forward? I'd be happy to commit to this, as the peer deps poses problems for monorepos in particular.
@Sonic12040 React 18 and MDX2 are aimed at being supported with V3: https://github.com/facebook/docusaurus/discussions/8469
Thanks for that. I'll see what's open to contribute to 3.0!