Conflicting versions when using canary releases + third-party plugins
Have you read the Contributing Guidelines on issues?
- [X] I have read the Contributing Guidelines on issues.
Prerequisites
- [X] I'm using the latest version of Docusaurus.
- [X] I have tried the
npm run clearoryarn clearcommand. - [X] I have tried
rm -rf node_modules yarn.lock package-lock.jsonand re-installing packages. - [ ] I have tried creating a repro with https://new.docusaurus.io.
- [ ] I have read the console error message carefully (if applicable).
Description
Let's imagine you are using a canary release of Docusaurus, and also a third-party plugin.
You likely have this in your package.json file:
"@docusaurus/core": "0.0.0-5170",
"@docusaurus/preset-classic": "0.0.0-5170",
"@easyops-cn/docusaurus-search-local": "^0.28.0",
Problem: @easyops-cn/docusaurus-search-local depends on many Docusaurus core packages with semver range ^2.0.0-beta.20, and ^2.0.0 does not match 0.0.0
This potentially leads to duplicate core package installs in your repo, and multiple versions of the same package being used at runtime.
This is particularly problematic for packages exporting React providers because contexts are now duplicated, leading to weird issues like this one https://github.com/facebook/docusaurus/issues/7686#issuecomment-1172377776
A workaround is to use things like npm/yarn resolutions so that the user forces the package manager to duplicate packages.
We'll probably move @docusaurus/theme-common to peerDependency in the future, as it's the package most likely to cause troubles (exporting many React contexts)
Another possibility is to change another time the canary versioning scheme, maybe using 3.0.0-something for the canaries after we release 2.0? This should be changed carefully, as this scheme has been the source of troubles in the past, see https://github.com/facebook/docusaurus/pull/5295)
Reproducible demo
No response
Steps to reproduce
see https://github.com/facebook/docusaurus/issues/7686#issuecomment-1172377776
Expected behavior
Use canary + third-party plugin without duplicated packages and weird React context issues
Actual behavior
see https://github.com/facebook/docusaurus/issues/7686#issuecomment-1172377776: unexpected React context issues
Your environment
- Public source code:
- Public site URL:
- Docusaurus version used:
- Environment name and version (e.g. Chrome 89, Node.js 16.4):
- Operating system and version (e.g. Ubuntu 20.04.2 LTS):
Self-service
- [ ] I'd be willing to fix this bug myself.
@slorber I'd like to add that the error messages can be highly confusing in this situation.
The F12 console error looks like this:
docsPreferredVersion.js:formatted:179 Uncaught ReactContextError
at useDocsPreferredVersionContext (docsPreferredVersion.js:formatted:179:15)
at useDocsPreferredVersionByPluginId (docsPreferredVersion.js:formatted:216:34)
at useContextualSearchFilters (searchUtils.js:21:543)
at useTypesenseContextualFilters (useTypesenseContextualFacetFilters.js:12:152)
at DocSearch (index.js:33:1501)
at renderWithHooks (react-dom.development.js:14985:18)
at mountIndeterminateComponent (react-dom.development.js:17811:13)
at beginWork (react-dom.development.js:19049:16)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945:14)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:16)
...and if you dig out the error string, it's complaining that useDocsPreferredVersionContext() was called outside of its <DocsPreferredVersionContextProvider> scope. I spent nearly 2 hours trying to debug that false premise. 😆
At first I was bisecting the Git history, looking for some Docusaurus release where <DocsPreferredVersionContextProvider> or some other part of the render tree might have been moved around. Then eventually I realized that there is in fact a <DocsPreferredVersionContextProvider> -- and useDocsPreferredVersionContext() does find it, but... not always?! This led into the react__WEBPACK_IMPORTED_MODULE_0__.useContext)(Context); and the sprawling logic fishing things out of contexts.
It was just a very unlucky direction to happen to choose for debugging: The reason why useDocsPreferredVersionContext() was failing is that it's defined in a secondary module, a different version of @docusaurus/theme-common that Webpack has found in node_modules and bundled for the third-party plugin. The <DocsPreferredVersionContextProvider> scope does exist, but its symbol doesn't match the useDocsPreferredVersionContext() instance that's trying to call it.
And so the fix is to override versions and eliminate the side-by-side versions from node_modules.
But wow, is there SOME WAY that Docusaurus's plugin framework could provide better safeguards or diagnostics for this trap? My scenario was pretty common -- just trying to upgrade Docusaurus, getting a weird crash, and believing what the error message was telling me. 🙂
Sorry about your experience
This kind of error can happen in any client-side app using npm unfortunately, and it's a quite common issue in React and Node.js world.
- The good thing is that at least you get an error.
- The worst thing could be that you inadvertently include multiple versions of React in your bundle, loading a lot of useless additional JS without even being aware of the problem.
But wow, is there SOME WAY that Docusaurus's plugin framework could provide better safeguards or diagnostics for this trap?
I don't have a clear answer to that. Maybe we could scan the node modules for duplicated packages or something 🤷♂️ Curious to know what others are doing to prevent this kind of issue.
I wish React would fail fast in such a case, but afaik since React 17 they support better micro-frontends and using multiple versions of React on the same page is perfectly allowed
Im not sure if this is related but is there a fixed for what you suggested @octogonz
I get the following

Using React 17.0.1 and Docusaurus 2.3.1
Im not sure if this is related but is there a fixed for what you suggested
@yannickrocks Yes, as I explained the problem is that two different instances of React got installed in the node_modules folder. Since we're using PNPM, we were able to use Lockfile Explorer to figure out the cause of this problem and fix it. Usually it just involves making the package.json versions consistent between projects, or sometimes adding an override such as .pnpmfile.cjs or Yarn "resolutions".