-
Notifications
You must be signed in to change notification settings - Fork 71
feat: enforce global singleton for all exposed modules via module federation #308
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
base: main
Are you sure you want to change the base?
Conversation
This PR introduces a robust singleton enforcement mechanism for all modules exposed via module federation in this package. The goal is to guarantee that, regardless of how or where an exposed module is imported (host, remote, or multiple remotes), only a single instance of that module is ever created and used within the same global context (e.g., browser window).
Thanks for your proposal @aachik-trimoz |
@@ -4,23 +4,31 @@ export const VIRTUAL_EXPOSES = 'virtual:mf-exposes'; | |||
export function generateExposes() { | |||
const options = getNormalizeModuleFederationOptions(); | |||
return ` | |||
const GLOBAL_KEY = '__MF_SINGLETONS__'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should not add more globals, this entire thing already exists in FEDERATION
should be using loadShare('lib', {from: 'name of current app'}); or at least from share_scope_map off federation
This will also not work with module layers which is being introduced, where you can have concurrent parallel share scopes who still respect singletons, but within the scope - so in cases like next, i have 13 singletons for react.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the tests I have made, the instance is not unique, so the instance may be recreated. I'd like to know what your approach is to avoid the problem of multiple instances
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be 1 instance per app. Recreation of instances shouldn't happen.
If thats is happening theres a bigger problem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instance is stored in memory / state and registered in the federation global, we search for the instance by name.
These arch specs may be useful. https://github.com/module-federation/core/pull/3955/files#diff-5596198c9d0ae99e768d378410829b221f2ac61b098aa86e5c55a994d6efb964
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may be the case for Webpack, but not for Vite. Based on my tests, I created an Axios instance with Keycloak for the token part and shared this instance with the other remotes. However, doing so resulted in the instances being created twice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah then its a bug in vite implementation. all webpack does is implement the runtime package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gioboa what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can totally trust @ScriptedAlchemy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gioboa do you think you can do an investigation to know why we don't have this in the Vite version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Id check why instances are recreated. In webpack. We do have 1 aspect where we assign the instance associated with that runtime to webpack_require. So we can access the instance throughout the application.
However I can also call init() multiple times over and it doesn't recreate the instance because we store it in a scoped variable - but thats what /runtime init does.
We did introduce createInstance now as well to runtime.
Purpose
This PR introduces a robust singleton enforcement mechanism for all modules exposed via module federation in this package. The goal is to guarantee that, regardless of how or where an exposed module is imported (host, remote, or multiple remotes), only a single instance of that module is ever created and used within the same global context (e.g., browser window).
Background
Previously, the plugin relied solely on the ES module system and browser module cache to ensure singleton behavior for exposed modules. However, in complex scenarios such as hot module replacement, dynamic imports, or certain micro-frontend setups, there was a risk that a module could be re-executed, resulting in multiple instances of what should be a singleton.
Why This Matters
Prevents duplicate singletons: Ensures that only one instance of critical modules (like HTTP clients, stores, or other stateful objects) exists per global context.
Improves reliability by reducing subtle bugs and inconsistencies that can arise from multiple instances, especially in large or dynamic micro-frontend architectures.
Transparent to consumers: No changes are required in consumer code; the singleton logic is handled automatically by the federation plugin.