module-federation / module-federation-examples

Implementation examples of module federation , by the creators of module federation
https://module-federation.io/
MIT License
5.67k stars 1.76k forks source link

Dynamic shared runtime exposed with Store lost shared data #4271

Open ytytsophia opened 2 months ago

ytytsophia commented 2 months ago

App1 and App2 are in different git repository App1 expose app1/getProjectId like :

class Store<T> {
  _value: T;

  set value(value: T) {
    this._value = value;
  }

  get value() {
    return this._value;
  }
}
const projectIdStore = new Store<string | undefined>();

const getProjectId = () => projectIdStore.value;

export const setProjectId = (value: string | undefined) =>
  (projectIdStore.value = value);
export default getProjectId;

I call setProjectId('1') in App1, and make app1/getProjectId shared in init functions like

shared: {
        react: {
          version: '17.0.2',
          scope: 'default',
          lib: () => React,
          shareConfig: {
            singleton: true,
            requiredVersion: '^17.0.2',
          },
        },
        'react-dom': {
          version: '17.0.2',
          scope: 'default',
          lib: () => ReactDOM,
          shareConfig: {
            singleton: true,
            requiredVersion: '^17.0.2',
          },
        },
        'project/getProjectId': {
          shareConfig: {
            singleton: true,
            requiredVersion: '^1.0.0',
          },
        },
      },

which I expect is in App2 , when I call app1/getProjectId, I can get the value which I set in App1 before, but I got undefined What should I suppose to do ? Thanks

ytytsophia commented 2 months ago

I saw https://github.com/module-federation/core/pull/2960/commits/ff5f03e1df14e925ec9521b8a2816f0a150be61b, Will this changes solve my problem? @ScriptedAlchemy

ScriptedAlchemy commented 2 months ago

Do you import the store as an exposed module, but the host also uses it? Is the host's remote entry loaded on the page as well?

ScriptedAlchemy commented 2 months ago

This is likely because the host has its own runtime, and so does the host's remote. So when importing an exposed module or using the "host's own remote" pattern, the exposed module in the remote entry runtime is empty. Since the host is using the module in its runtime graph and not its remotes, there are two instances of the module:

  1. In the host's main.js webpack module cache
  2. In the remote entry module cache

You can try runtimeChunk: single and can look at the single runtime chunk example for webpack-based builds in runtime plug-ins of the examples repository.

ytytsophia commented 2 months ago

Thanks for response But if I set runtimeChunk : single in optimization, I got errors like

image

and the building got stuck, When I used webpack/lib/container/ModuleFederationPlugin , there were no errors

ytytsophia commented 2 months ago

I wonder if the new plugin : '@module-federation/enhanced/webpack' implicitly set runtime false ?

ScriptedAlchemy commented 2 months ago

I set the runtime as false when i detect single runtime chunk. in webpack it should create a partial chunk or on later version now of enhanced, it should bundle the remote into the host runtime, so that by loading th host webpack runtime, it has side effect of setting get,init on the global interface to you never need to load the hosts own remote.js - this is how i do it in next.js

ytytsophia commented 1 month ago

We have now switched from Webpack to Rsbuild, but I’ve found that the problem still persists: the host and remote are not sharing the runtime. Note that runtimeChunk: 'single' is set in the optimization configuration.

ScriptedAlchemy commented 1 month ago

provide repo