docusaurus icon indicating copy to clipboard operation
docusaurus copied to clipboard

Conflicting versions when using canary releases + third-party plugins

Open slorber opened this issue 3 years ago • 2 comments

Have you read the Contributing Guidelines on issues?

Prerequisites

  • [X] I'm using the latest version of Docusaurus.
  • [X] I have tried the npm run clear or yarn clear command.
  • [X] I have tried rm -rf node_modules yarn.lock package-lock.json and 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 avatar Jul 06 '22 14:07 slorber

@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. 🙂

octogonz avatar Aug 12 '22 11:08 octogonz

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

slorber avatar Aug 24 '22 15:08 slorber

Im not sure if this is related but is there a fixed for what you suggested @octogonz I get the following image

Using React 17.0.1 and Docusaurus 2.3.1

yannickrocks avatar Feb 28 '23 10:02 yannickrocks

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".

octogonz avatar Feb 28 '23 19:02 octogonz