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

Federated Modules: Dynamic Remotes #11033

Open
ahmadsholehin opened this issue Jun 13, 2020 · 48 comments
Open

Federated Modules: Dynamic Remotes #11033

ahmadsholehin opened this issue Jun 13, 2020 · 48 comments
Labels
module-federation issues related to module federation

Comments

@ahmadsholehin
Copy link

Feature request

What is the expected behavior?
It seems that although dynamic imports are supported in federated modules, and it is possible to obtain remoteEntry.js on runtime, the remotes are still statically defined in webpack config.

new ModuleFederationPlugin({
      name: 'application_b',
      library: { type: 'var', name: 'application_b' },
      filename: 'remoteEntry.js',
      exposes: {
        'SayHelloFromB': './src/app',
      },
      remotes: {
        'application_a': 'application_a',
      },
      shared: ['react', 'react-dom'],
    }),

Here, application_b is statically defining application_a as a remote.

Is there a way that remotes can be defined dynamically instead?

What is motivation or use case for adding/changing the behavior?

A plugin system that spreads its plugins over many microservices.

How should this be implemented in your opinion?

Similar to lazy loading in code splitting, could dynamic imports (remotes) be preemptively prepared?

Are you willing to work on this yourself?
I am not very well-versed in webpack's internals, unfortunately.

@sokra
Copy link
Member

sokra commented Jun 15, 2020

You can dynamically load remote modules using this:

// Initializes the share scope.
// This fills it with known provided modules from this build and all remotes
await __webpack_init_sharing__("default");
// TODO: load the script tag somehow. e. g. with a script loader
const container = window.application_a;
// Initialize the container, it may provide shared modules
await container.init(__webpack_share_scopes__.default);
const module = await container.get("./module");

@ScriptedAlchemy
Copy link
Member

await __webpack_init_sharing__("default"); not initialize

@sokra
Copy link
Member

sokra commented Jul 14, 2020

Thanks fixed

@shaodahong
Copy link
Contributor

In the actual project, services in remote host, and we may be exposed multiple module, can we do this?

const { Routes, Button } = await __webpack_init_module_federation_remote('https://localhost/order/remoteEntry.js');

@davewthompson
Copy link

davewthompson commented Oct 19, 2020

@shaodahong It's completely possible to dynamically import modules; we use the following code to load the compiled code into the window object dynamically:

   await new Promise((resolve, reject) => {
      const element = document.createElement('script');

      element.src = url;
      element.type = 'text/javascript';
      element.async = true;

      element.onload = () => {
        element.parentElement.removeChild(element);
        resolve();
      };
      element.onerror = (error) => {
        element.parentElement.removeChild(element);
        reject(error);
      };

      document.head.appendChild(element);
    });

  const factory = await window[webpackModuleName].get(component);
  return factory();

Note this doesn't seem to work properly when you have multiple plugins with identical component names running in development mode with HMR.

@shaodahong
Copy link
Contributor

yup, it's broken when using dev hmr

@ScriptedAlchemy
Copy link
Member

HMR and MF do not work currently.

@shaodahong
Copy link
Contributor

HMR and MF do not work currently.

@ScriptedAlchemy webpack/webpack-dev-server#2692 Any plan?

@royriojas
Copy link

hi @ScriptedAlchemy and @sokra

Just wanted to confirm if it is actually possible to load dynamically federated modules from a dynamically loaded remote. It seems it is possible. I will give it a try to the code @sokra put above, but would be nice to get a confirmation from you that it is actually possible.

@davewthompson
Copy link

@royriojas check my code above: #11033 (comment). We have this working fine in dev loading federated modules just using a URL.

@ScriptedAlchemy
Copy link
Member

ScriptedAlchemy commented Oct 21, 2020

You're likely not running remote containers over wds. The issue appears when WDS is used to host containers. I've experienced this issue and it still remains. Though I've not tested with webpack-cli/serve

I've not looked into webpack dev server or this issue further. A workaround you could apply is to add startup code and manually define the container to the window. Since WDS adds a module to the end, we can use startup code to add our own module and basically set it ourselves.

https://link.medium.com/ierojo0DKab

@royriojas
Copy link

Hi @ScriptedAlchemy based on all that I've found I came with this for dynamic loading modules from remotes (without hardcoding them in the webpack config)

https://github.com/royriojas/mfe-webpack-demo/tree/attempt_dynamic

But here is something very weird I noticed:

React from app_03 is resolved to the same React in that remote if not loaded before executing any code from the app_01. Not sure if it is a bug or it is intended to be like that. But since what I want is to load arbitrary code without caring about the order, this might be a deal breaker. Well not really, but it will force us to think of a workaround (like preload certain dependencies in a vendors.js file maybe?

If you comment this line here: https://github.com/royriojas/mfe-webpack-demo/blob/attempt_dynamic/packages/app-01/src/index.jsx#L8 you will see that the app fails to load the app_03

For now preloading it solves my issue, but it would be really nice to not need that.

The error that I get when I don't preload that given remote is that there are 2 React versions in the page :(

@royriojas
Copy link

royriojas commented Oct 21, 2020

This is the error, if @sokra or @ScriptedAlchemy or anybody knows why does this error happen.

react.development.js:1465 Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
    at resolveDispatcher (react.development.js:1465)
    at useDebugValue (react.development.js:1529)
    at styled-components.browser.esm.js:1
    at styled.button (styled-components.browser.esm.js:1)
    at renderWithHooks (react-dom.development.js:14825)
    at updateForwardRef (react-dom.development.js:16840)
    at mountLazyComponent (react-dom.development.js:17392)
    at beginWork (react-dom.development.js:18635)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
resolveDispatcher @ react.development.js:1465
useDebugValue @ react.development.js:1529
(anonymous) @ styled-components.browser.esm.js:1
styled.button @ styled-components.browser.esm.js:1
renderWithHooks @ react-dom.development.js:14825
updateForwardRef @ react-dom.development.js:16840
mountLazyComponent @ react-dom.development.js:17392
beginWork @ react-dom.development.js:18635
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
beginWork$1 @ react-dom.development.js:23234
performUnitOfWork @ react-dom.development.js:22185
workLoopSync @ react-dom.development.js:22161
performSyncWorkOnRoot @ react-dom.development.js:21787
(anonymous) @ react-dom.development.js:11111
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11061
flushSyncCallbackQueueImpl @ react-dom.development.js:11106
workLoop @ scheduler.development.js:597
flushWork @ scheduler.development.js:552
performWorkUntilDeadline @ scheduler.development.js:164
react_devtools_backend.js:2273 The above error occurred in the <styled.button> component:
    in styled.button (created by UiLibraryPage)
    in Suspense (created by UiLibraryPage)
    in div (created by Page)
    in div (created by Page)
    in Page (created by UiLibraryPage)
    in UiLibraryPage (created by Context.Consumer)
    in Route (created by Routes)
    in Switch (created by Routes)
    in Routes (created by App)
    in div (created by App)
    in Router (created by HashRouter)
    in HashRouter (created by App)
    in App

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
overrideMethod @ react_devtools_backend.js:2273
logCapturedError @ react-dom.development.js:19560
logError @ react-dom.development.js:19597
update.callback @ react-dom.development.js:20741
callCallback @ react-dom.development.js:12512
commitUpdateQueue @ react-dom.development.js:12533
commitLifeCycles @ react-dom.development.js:19916
commitLayoutEffects @ react-dom.development.js:22834
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
commitRootImpl @ react-dom.development.js:22572
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11061
commitRoot @ react-dom.development.js:22412
finishSyncRender @ react-dom.development.js:21838
performSyncWorkOnRoot @ react-dom.development.js:21824
(anonymous) @ react-dom.development.js:11111
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11061
flushSyncCallbackQueueImpl @ react-dom.development.js:11106
workLoop @ scheduler.development.js:597
flushWork @ scheduler.development.js:552
performWorkUntilDeadline @ scheduler.development.js:164

@ScriptedAlchemy
Copy link
Member

ScriptedAlchemy commented Oct 21, 2020

You can't unload react and magically load another copy. Webpack can only negotiate versions sharing of singletons upfront.

Only use module-federation-examples for configuring. Your webpack config is old and you're sharing api isn't right for what you're trying to do.

Please refer to my repos under the MF organization.

One look at your repo, you're not using semver sharing, webpack probably doesn't know if it can / should share. React also needs to be a singleton to function.

You can upgrade to react 17 if you need multiple copies of react for whatever reason

@royriojas
Copy link

@ScriptedAlchemy I don't want to load two versions of react. I actually want to share the same React version across the board. I will check the webpack config, but I was sure I recently upgraded it.

I'm not trying to share anything yet. I was just trying to understand what was possible to do with module federation. I will take a look a semver sharing.

Thank you for your feedback.

@royriojas
Copy link

royriojas commented Oct 21, 2020

Thanks for your feedback @ScriptedAlchemy. Using a shared singleton fixed all the issues I had. Thank u. 👍

royriojas/mfe-webpack-demo@4711f37#diff-3d864b4f5a6e000cbf1420a6b94dd5ce3688b24b01a3cff1ecb817e8e5f44708R46

@ScriptedAlchemy
Copy link
Member

Yeeeeee!!! 🥳

Thrilled it resolved the problem.
Where did you read about the old config? Or is this just an old copy from beta 16 that you've been using.

Need to know if I should actually update my articles or not 😂😂

@royriojas
Copy link

@ScriptedAlchemy Old example forked from https://github.com/mizx/mfe-webpack-demo which was using the beta version

@ScriptedAlchemy
Copy link
Member

Ahhh yep. He helped me build out some examples, he was the first outside user. Module federation examples was actually based on his initial effort to help us make example projects. Will DM and see if he wants to drop a link or update some examples

@ksrb
Copy link

ksrb commented Dec 16, 2020

For anyone googling into this, the module federation documentation has been updated and a example added:

So I have issue, I have code loading in modules 'synchronously' so something like:

import urls from "remoteModule/constants";

async function getSomething(params) {
  // ...Other processing
  return fetch(urls.aThing);
}

Unless I'm misunderstanding something, the technique used in the example wouldn't work for what I'm trying to do?

Or I would have to restructure my code to be something like:

async function getSomething(params) {
  const { aThing } = await someKindOfDynamicLoading("remoteModule/constants");
    // ...Other processing
  return fetch(urls.aThing);
}

The thing is I really don't want to do that, I guess the argument could be made that it should be explicit whether a module is being loaded externally via a function like someKindOfDynamicLoading, but for 'middleware'/non-jsx code it seems out of place?

Is there a way to modify the example(s) given so that I could load my modules synchronously? Or am I'm using federated modules in a 'unintended'/bad way?

Update: Several community members helped and figured out the issue mentioned in this comment, a example is now available under: advanced-api/dynamic-remotes-synchronous-imports

@webpack-bot
Copy link
Contributor

This issue had no activity for at least three months.

It's subject to automatic issue closing if there is no activity in the next 15 days.

@somsharp
Copy link

You can dynamically load remote modules using this:

// Initializes the share scope.
// This fills it with known provided modules from this build and all remotes
await __webpack_init_sharing__("default");
// TODO: load the script tag somehow. e. g. with a script loader
const container = window.application_a;
// Initialize the container, it may provide shared modules
await container.init(__webpack_share_scopes__.default);
const module = await container.get("./module");

I am able to load remote module dynamically with the above approach. Just curious if I can pass props to the remote component? If yes, refer some sample code please!

@royriojas
Copy link

royriojas commented Apr 12, 2021

const factory = await container.get(moduleToLoad); // where moduleToLoad is the path to the module (including a `/.` if I recall correctly
const Module = factory();

Module.default(/* pass props here*/); // this is the function, or component or whatever that is being federated

@somsharp
Copy link

const factory = await container.get(moduleToLoad); // where moduleToLoad is the path to the module (including a `/.` if I recall correctly
const Module = factory();

Module.default(/* pass props here*/); // this is the function, or component or whatever that is being federated

@royriojas thank you for your reply. I was trying the follow the steps you mentioned. But now luck. In my component I have a property called 'name' with a type of string I was trying to pass the data like Module.default({name:'abcd'}) which did not work Also I tried with Module.default(name='abcd') which is also not working. Can you please help me here.

@royriojas
Copy link

royriojas commented Apr 13, 2021 via email

@somsharp
Copy link

How are you exporting your component? is that the default? otherwise you might not need the default keyword Roy Ronald Riojas Montenegro

On Mon, Apr 12, 2021 at 5:04 PM Somnath @.*> wrote: const factory = await container.get(moduleToLoad); // where moduleToLoad is the path to the module (including a /. if I recall correctlyconst Module = factory(); Module.default(/ pass props here/); // this is the function, or component or whatever that is being federated @royriojas https://github.com/royriojas thank you for your reply. I was trying the follow the steps you mentioned. But now luck. In my component I have a property called 'name' with a type of string I was trying to pass the data like Module.default({name:'abcd'}) which did not work Also I tried with Module.default(name='abcd') which is also not working. Can you please help me here. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#11033 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABABWSINU5VQRE6Z2QPYSTTIODCXANCNFSM4N5DZLIA .

I am exporting as default. Here is the snippet :

import * as React from "react";
interface OwnProps {
name: string;
}
const Widget: (React.FC) = props => {
const renderMain = (): JSX.Element => {
return (
<div
// my additional implementation goes here
{props.children}

);
}
return renderMain();
}
export default Widget;

I am loading the above component from my host app port 3001 and remote component is running in port 3002

@royriojas
Copy link

royriojas commented Apr 13, 2021 via email

@somsharp
Copy link

Could you share your webpack config for remotes? Roy Ronald Riojas Montenegro

On Mon, Apr 12, 2021 at 5:22 PM Somnath @.> wrote: How are you exporting your component? is that the default? otherwise you might not need the default keyword Roy Ronald Riojas Montenegro … <#m_2640954308268869088_> On Mon, Apr 12, 2021 at 5:04 PM Somnath @.> wrote: const factory = await container.get(moduleToLoad); // where moduleToLoad is the path to the module (including a /. if I recall correctlyconst Module = factory(); Module.default(/ pass props here/); // this is the function, or component or whatever that is being federated @royriojas https://github.com/royriojas https://github.com/royriojas thank you for your reply. I was trying the follow the steps you mentioned. But now luck. In my component I have a property called 'name' with a type of string I was trying to pass the data like Module.default({name:'abcd'}) which did not work Also I tried with Module.default(name='abcd') which is also not working. Can you please help me here. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#11033 (comment) <#11033 (comment)>>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABABWSINU5VQRE6Z2QPYSTTIODCXANCNFSM4N5DZLIA . I am exporting as default. Here is the snippet : import * as React from "react"; interface OwnProps { name: string; } const Widget: (React.FC) = props => { const renderMain = (): JSX.Element => { return ( <div // my additional implementation goes here {props.children} ); } return renderMain(); } export default Widget; I am loading the above component from my host app port 3001 and remote component is running in port 3002 — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#11033 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABABWRZMCU7N3GFD7RA3ZLTIOFGBANCNFSM4N5DZLIA .

const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack").container
.ModuleFederationPlugin;
const path = require("path");

module.exports = {
entry: "./src/index",
mode: "development",
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 3002,
},
output: {
publicPath: "auto",
},
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
module: {
rules: [
{
test: /bootstrap.tsx$/,
loader: "bundle-loader",
options: {
lazy: true,
},
},
{
test: /.tsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
presets: ["@babel/preset-react", "@babel/preset-typescript"],
},
},
],
},
plugins: [
new ModuleFederationPlugin({
name: "app2",
filename: "remoteEntry.js",
exposes: {
"./Button": "./src/Button",
"./Widget": "./src/Widget",
},
shared: ["react", "react-dom"],
}),
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
],
};

@grzegorzjudas
Copy link

For people not sure how to implement this for React lazy loaded components, assuming you have the following config available (hardcode it, preload it, add using SSR, or whatever other method of choice):

/* This is basically the same object you'd have in webpack config */
window.__remotes__ = {
    'myapp': 'myapp@http://localhost:9001/remoteEntry.js'
};

do:

declare global {
    interface Window {
        __remotes__: Record<string, string>;
    }

    const __webpack_init_sharing__: any;
    const __webpack_share_scopes__: any;
}
async function dynamicImport (path: string) {
    const [ remoteName, remoteUrl ] = Object.entries(window.__remotes__).find(([ r ]) => path.startsWith(r));

    if (!remoteName) throw new Error(`URL not configured for remote '${path}'.`);
    if (remoteUrl.split('@').length !== 2) throw new Error(`URL misconfigured for remote '${path}'`);

    const [ moduleName, moduleUrl ] = remoteUrl.split('@');

    await __webpack_init_sharing__('default');

    await new Promise<void>((resolve, reject) => {
        const element = document.createElement('script');

        element.src = moduleUrl;
        element.type = 'text/javascript';
        element.async = true;

        element.onload = () => {
            element.parentElement.removeChild(element);
            resolve();
        };

        element.onerror = (err) => {
            element.parentElement.removeChild(element);
            reject(err);
        };

        document.head.appendChild(element);
    });

    const container = window[moduleName];
    await container.init(__webpack_share_scopes__.default);

    const component = `.${path.replace(remoteName, '')}`;
    const factory = await container.get(component);

    return factory();
}

and then just replace import(...) with dynamicImport:

const MyComponent = React.lazy(() => dynamicImport('myapp/MyComponent'));

@grzegorzjudas
Copy link

Btw, @sokra @ScriptedAlchemy - are these __webpack_init_sharing__ and __webpack_share_scopes__ going to be added to @types/webpack-env? Is that package owned by webpack team?

@sokra
Copy link
Member

sokra commented May 7, 2021

Is that package owned by webpack team?

nope, but we could add that to our own typings...

@levanify
Copy link

levanify commented Jun 14, 2021

@sokra @ScriptedAlchemy I'm able to load the component dynamically, however, it seems like host container cannot share the React Context with the Remote container. Do you have any idea why? I have been stuck at this for some time

I tried to combine these 2 examples to enable the remote containers to consume context from the host container, but it doesn't seem to work:

@ScriptedAlchemy
Copy link
Member

It should work. Is more than one copy of react getting loaded? If not then I don't see a reason why it wouldn't work.

Are you perhaps not sharing something that depends on react context. Like a node module

@levanify
Copy link

levanify commented Jun 15, 2021

Thank you @ScriptedAlchemy for your reply. Really appreciate it!

Is more than one copy of react getting loaded?

I'm loading just one copy of react, I'm setting the webpack config for both host and remote containers to be

react: { singleton: true, requiredVersion: deps['react'] }

If I understand correctly, singleton would ensure that only one copy of react is loaded

Are you perhaps not sharing something that depends on react context. Like a node module

May I clarify what do you mean by this?

EDIT:
I managed to make it work with the example repo. However, I realise that the example repo is using yarn workspaces. I'm having difficulty in replicating it in my own project using npm lerna setup. Do you know whether this could be the source of the issue?

@ScriptedAlchemy
Copy link
Member

Regarding dynamic remotes. They might be getting initialized too late or early, a remote can only be initialized once so if it depends on something from another remotes share scope as a singleton, the scare scopes cannot be reinitialized with more modules at a later stage.

@vankop vankop added the module-federation issues related to module federation label Nov 23, 2021
@pbn04001
Copy link

pbn04001 commented Feb 4, 2022

I have tried the mentioned by @grzegorzjudas, but I can't get past this error
TypeError: __webpack_init_sharing__ is not a function

Is there something else I am needing to expose these values?

@ScriptedAlchemy
Copy link
Member

That won't work if your consuming app doesn't have anything shared. If you're not planning to share any modules from the consuming app then you don't want to init sharing since there's nothing to share.

@MichaelDurfey
Copy link

I created a library that abstracts some of the business logic and works for suspense, loadable or others https://github.com/MichaelDurfey/mf-dynamic-remote-component

@ScriptedAlchemy
Copy link
Member

@MichaelDurfey nice. Would love to house this under the federation git organization if you’d want to maintain it there. Utilities like this make or break the experience :)

@MichaelDurfey
Copy link

@ScriptedAlchemy Sounds good to me!

@DhruvilPatel19
Copy link

@ScriptedAlchemy I Want to know how we can dynamically fetch remotes on server-side (in node server)
also If we are able to fetch remote components on server then I believe it's async process
then how we can make it synchronous process as we can't add 'await' to renderToString() ?

@ScriptedAlchemy
Copy link
Member

ScriptedAlchemy commented Aug 27, 2022

The node technology is currently proprietary.

There's a package on npm called node-mf, it's the least buggy option.

I do plan to release module-federation/node in the near future.

Our internal technology is the the most stable and powers many enterprise clients. It's also what's powering SSR support on next.js and is the core tech running module-federation/aegis (hexagonal backend architecture that enables federation for any language on any compute primitive)

Also works sync or async

@tzachbon
Copy link

For people not sure how to implement this for React lazy loaded components, assuming you have the following config available (hardcode it, preload it, add using SSR, or whatever other method of choice):

/* This is basically the same object you'd have in webpack config */
window.__remotes__ = {
    'myapp': 'myapp@http://localhost:9001/remoteEntry.js'
};

do:

declare global {
    interface Window {
        __remotes__: Record<string, string>;
    }

    const __webpack_init_sharing__: any;
    const __webpack_share_scopes__: any;
}
async function dynamicImport (path: string) {
    const [ remoteName, remoteUrl ] = Object.entries(window.__remotes__).find(([ r ]) => path.startsWith(r));

    if (!remoteName) throw new Error(`URL not configured for remote '${path}'.`);
    if (remoteUrl.split('@').length !== 2) throw new Error(`URL misconfigured for remote '${path}'`);

    const [ moduleName, moduleUrl ] = remoteUrl.split('@');

    await __webpack_init_sharing__('default');

    await new Promise<void>((resolve, reject) => {
        const element = document.createElement('script');

        element.src = moduleUrl;
        element.type = 'text/javascript';
        element.async = true;

        element.onload = () => {
            element.parentElement.removeChild(element);
            resolve();
        };

        element.onerror = (err) => {
            element.parentElement.removeChild(element);
            reject(err);
        };

        document.head.appendChild(element);
    });

    const container = window[moduleName];
    await container.init(__webpack_share_scopes__.default);

    const component = `.${path.replace(remoteName, '')}`;
    const factory = await container.get(component);

    return factory();
}

and then just replace import(...) with dynamicImport:

const MyComponent = React.lazy(() => dynamicImport('myapp/MyComponent'));

How do you handle errors from the script tag?
For example, there was an issue loading the remote entry because of a missing chunk.

@digitalhank
Copy link

digitalhank commented Feb 8, 2023

How do you handle errors from the script tag? For example, there was an issue loading the remote entry because of a missing chunk.

@tzachbon
Try defining this in the remote's Webpack config

output {
  publicPath: 'auto'
}

I believe the remote is trying to fetch its resources on the host instead of its own server. Webpack is clever enough to resolve this for you. See here

@ScriptedAlchemy
Copy link
Member

If you only need dynamic connection code, im working on delegate modules - have just released it for next.js and will work on normal support.

This lets you use static imports, but can dynamically resolve the location of the remote container as needed.

module-federation/module-federation-examples#2756
https://github.com/module-federation/universe/tree/main/packages/nextjs-mf#beta-delegate-modules

@grzegorzjudas
Copy link

@tzachbon You could return a custom function that wraps factory() in try/catch clause. Haven't tried it, but something along this should work:

return () => {
    try {
        factory();
    } catch (err) {
        // handle the error somehow
    }
};

@goldyfruit
Copy link

goldyfruit commented Oct 8, 2023

I got stuck with Vite for few days originjs/vite-plugin-federation#518 (and I started to be desperate) until I found this issue @MichaelDurfey library.

This library was a gem to me 👍

Thanks again!

@FaureWu
Copy link

FaureWu commented Jul 8, 2024

Currently, I have a solution to the problem of dynamic remote: The general effect is as follows:

// You can pull the remote url configuration here through code or requests
window.remote_urls = {
    app: 'http://localhost:3000/',
}

import('./bootstrap')

And you can use it as follows:

// Suppose./Button is exported in the app
import Button from 'remote:app/Button'
function Demo() {
    return <Button />;
}

I have currently implemented this pattern in my own scaffolding, and if you are interested, I will take the time to introduce it completely as above.

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

No branches or pull requests