Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I use mf in react with 「externals」? #3467

Open
qiujie8092916 opened this issue Dec 8, 2023 · 6 comments
Open

How can I use mf in react with 「externals」? #3467

qiujie8092916 opened this issue Dec 8, 2023 · 6 comments

Comments

@qiujie8092916
Copy link

Hi, I am using module federation to build a application

my remote webpack conf:

// remote webpack
shared: {
  ...deps,
  react: {
    singleton: true,
    import: false,
    eager: false,
    version: '0',
    requiredVersion: "*"
  },
  'react-dom': {
    singleton: true,
    import: false,
    eager: false,
    version: '0',
    requiredVersion: "*"
  },
},

my host webpack conf:

// host webpack
shared: {
  react: {
    eager: true,
    singleton: true,
    requiredVersion: "16.14.0"
  },
  'react-dom': {
    eager: true,
    singleton: true,
    requiredVersion: "16.14.0"
  }
},
//...
externals: {
  react: 'React',
  'react-dom': 'ReactDOM'
},

And I use <script> to import react and react-dom from public/index.html

I got an error:
image

what should I do?
thanks for your help

@ScriptedAlchemy
Copy link
Member

ScriptedAlchemy commented Jan 14, 2024

You can use

https://github.com/module-federation/universe/tree/main/packages/runtime
https://github.com/module-federation/universe/tree/main/packages/enhanced
or use rspack

i believe runtimePlugin will be what you want to look at writing. resolveShare might be the hook for you.

You can share the library as import:false

{react: {import:false}}

then in a runtimePlugin, you can use resolveShare hook,

OR

you can use federation runtime and init({mfConfig}).

import { init, loadRemote, loadShare } from '@module-federation/runtime';

init({
  name: '@demo/main-app',
  remotes: [],
  shared: {
    react: {
      version: '17.0.0',
      scope: 'default',
      lib: () => window.React,
      shareConfig: {
        singleton: true,
        requiredVersion: '^17.0.0',
      },
    },
    'react-dom': {
      version: '17.0.0',
      scope: 'default',
      lib: () => window.ReactDOM,
      shareConfig: {
        singleton: true,
        requiredVersion: '^17.0.0',
      },
    },
  },
});

@qiujie8092916
Copy link
Author

Are there any examples of better integration with umijs?

@ScriptedAlchemy
Copy link
Member

No but I can make one, or if you have a basic host remote with the framework, send me a PR and I’ll make it do whatever you’re wanting it to do.

@qiujie8092916
Copy link
Author

qiujie8092916 commented Jan 25, 2024

No but I can make one, or if you have a basic host remote with the framework, send me a PR and I’ll make it do whatever you’re wanting it to do.

Thanks a lot. We are exploring the module federation in our project. Our projects are all based on UmiJs@3 and UmiJs@4.
#3608

@qiujie8092916
Copy link
Author

In addition, the umd library may be dynamic, not limited to just react and react-dom. If using runtimePlugin, can dynamic umd libraries be passed in through function parameters?
Similar to:

// webpack.config.ts
const externals = {
  react: "window.React",
  "react-dom": "window.ReactDOM",
};
// ...	
runtimePlugins: [require.resolve('./runtime.js')(externals)],
// runtime.js
import type { FederationRuntimePlugin } from '@module-federation/runtime/types';

export default function (umds): FederationRuntimePlugin {
  return {
    name: 'umd-library-shared-plugin',
    resolveShare(args: any) {
      const { shareScopeMap, scope, pkgName, version } = args;

      if (!Object.keys(umds).includes(pkgName)) {
        return args;
      }

      args.resolver = function () {
      	shareScopeMap[scope][pkgName][version] = eval(umds[pkgName]);
      	return shareScopeMap[scope][pkgName][version];
      };
    },
  };
}

@ScriptedAlchemy
Copy link
Member

that should work. You can probbably set import: false for react and whatever else, not externals. Since resolveShare can resolve it to window for you, webpack doesnt need to know about it import:false is "externals" via federation sharing negotiation, which you can control with that runtime plugin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants