module-federation/core

Federation Runtime not sharing same react context

Closed this issue · 12 comments

Describe the bug

I have a external lib that creates a react context.
I'm using that lib in both remote and shell apps.
The shell app is sharing the lib as singleton, but the remote app can't get the same react context.
I'm confusing if it is a issue of Module Federation or not.

Reproduction

https://github.com/douglaszaltron/practical-module-federation

Used Package Manager

pnpm

System Info

System:
    OS: Linux 5.14 Ubuntu 22.04.4 LTS 22.04.4 LTS (Jammy Jellyfish)
    CPU: (8) x64 Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
    Memory: 6.96 GB / 15.40 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 20.15.0 - ~/.nvm/versions/node/v20.15.0/bin/node
    npm: 10.7.0 - ~/.nvm/versions/node/v20.15.0/bin/npm
    pnpm: 9.5.0 - ~/.nvm/versions/node/v20.15.0/bin/pnpm
  Browsers:
    Chrome: 127.0.6533.88

Validations

The runtime init has no get or lib attributes. Read the docs. You can't just specify versions of stuff without the getter for the thing itself.

The runtime init has no get or lib attributes. Read the docs. You can't just specify versions of stuff without the getter for the thing itself.

After reviewing the documentation, I couldn't fully understand how sharing works in runtime mode. Do you have an example of usage? It might become clearer with a practical example. Even in this repo, with a code snippet that we can modify.

I'm a bit confused about the sharing between the remote and the shell. 🤔 💭

@zhoushaw I noticed that you had created a runtime app example. Maybe you can help us. In this example, is there anything that we need to modify to make the sharing work? It would be a great addition to the repo, as I believe others might encounter this issue or need this concept.

const root = ReactDOMClient.createRoot(info.dom);

Another question came up. While reviewing the bridge's source code, I noticed that when using a shared component together, the providers won't be shared because a new React "root" is created in each microfrontend. As a result, the React tree becomes separate, preventing the context from propagating since a new instance will be recreated. Is that correct?

@ScriptedAlchemy @zhoushaw

Yes thats correct, since the bridge is a new react app. You can always pass the provider back down again to proxy it back through.

Yes thats correct, since the bridge is a new react app. You can always pass the provider back down again to proxy it back through.

I didn't quite understand the last statement about passing the provider down.

In the examples, I couldn't get the same instance of the provider, as it always recreates the state.

After running some tests, I was able to propagate and use the same instance using runtime, but when used together with the bridge, it didn't work.

Is there any way to recover the instance and propagate the changes using the bridge?

get the context and pass it as props.

parentContext = useContext(parent)

Something like that, you will have to proxy the context through since its another app tree.

Today, I find myself limited when using the bridge because I need to share contexts such as authentication, authorization, user data, and queries. This lack of straightforward sharing hinders my ability to distribute tasks across segmented teams.

It would be highly beneficial if the plugin (SDK) had an option to enable or disable context sharing, allowing the same React tree to be used.

Currently, we have a solution where we modify react-router-dom using history, changing the basename, and allowing the use of two BrowserRouter instances. This way, the remote application checks if a provider exists and uses the host's provider. However, there are still some bottlenecks that the bridge has resolved, which don't depend on the react-router-dom version, unlike our approach, which is strictly version-dependent.

Nevertheless, I would like to suggest an improvement.

If possible, it would be very helpful to include this use case of context sharing in the examples, as it would greatly aid our understanding. The current explanation about using the provider's proxy is still quite unclear.

Thank you.

I'll look into a example of cross app context share. The problem in general though is that this might not be possible for us to automate context discovery. Since you mave many providers and since these are implicit dependencies somewhere else, these providers etc are registered internally inside the react instance. When mounting another application, it uses a different instance of react. React doesn't have something like React.getAllContextProvidersInTree so we have no way to know what or where you might put something.

Tks! 🚀