Module Federation Runtime APIs; Available in Rspack & Webpack #1936
Replies: 4 comments 10 replies
-
Hi! Thank you for all your work! |
Beta Was this translation helpful? Give feedback.
-
Hello Zack! Thx a lot for new release and I've a question: I've multiple dependencies of the same packages with different major versions (by package alias in package.json). Module Federation v1 (old)Expected resultBoth major versions of antd are shared Input configconst moduleFederationConfig = {
name: 'app_demo',
filename: `remoteEntry.js?v=[contenthash]`,
shared: {
react: { shareKey: 'react', requiredVersion: '18.2.0', singleton: true },
'react-dom': {
shareKey: 'react-dom',
requiredVersion: '18.2.0',
singleton: true,
},
antd: {
shareKey: 'antd',
requiredVersion: '5.13.2',
singleton: false,
},
'antd-4': {
shareKey: 'antd',
requiredVersion: '^4.0.0',
singleton: false,
},,
}; Webpack share scopes result:{
"default": {
"antd": {
"4.24.15": {
"from": "node-starter",
"eager": false,
"loaded": 1
},
"5.13.2": {
"from": "node-starter",
"eager": false,
"loaded": 1
}
},
"react-dom": {
"18.2.0": {
"from": "node-starter",
"eager": false,
"loaded": 1
}
},
"react": {
"18.2.0": {
"from": "node-starter",
"eager": false,
"loaded": 1
}
}
}
} Actual resultBoth versions of antd are shared (expected result is equal) Module Federation v1.5 (new)Expected resultBoth major versions of antd are shared Actual resultMF picks one of them (the first one) Input (the same like v1)Output (FEDERATION.SHARE):{
"app_demo": {
"default": {
"antd": {
"4.24.15": {
"deps": [],
"useIn": [
"app_demo"
],
"from": "app_demo",
"loading": null,
"version": "4.24.15",
"scope": [
"default",
"default"
],
"shareConfig": {
"requiredVersion": "^4.24.15",
"singleton": false,
"eager": false,
"strictVersion": false
},
"loaded": true,
"strategy": "version-first"
}
},
"react-dom": {
"18.2.0": {
"deps": [],
"useIn": [
"app_demo"
],
"from": "app_demo",
"loading": null,
"version": "18.2.0",
"scope": [
"default"
],
"shareConfig": {
"requiredVersion": "^18.2.0",
"singleton": false,
"eager": false,
"strictVersion": false
},
"loaded": true,
"strategy": "version-first"
}
},
"react": {
"18.2.0": {
"deps": [],
"useIn": [
"app_demo"
],
"from": "app_demo",
"loading": null,
"version": "18.2.0",
"scope": [
"default"
],
"shareConfig": {
"requiredVersion": "^18.2.0",
"singleton": false,
"eager": false,
"strictVersion": false
},
"loaded": true,
"strategy": "version-first"
}
}
}
}
} I'm guessing it has to do with the new strategy field, which defaults to 'version-first'. How to fix it? Example repo: |
Beta Was this translation helpful? Give feedback.
-
Sorry for asking a old webpack internal MF plugin question. how to catch the |
Beta Was this translation helpful? Give feedback.
-
There seems to be no support for vite, the plugin is packaged with esm, federation runtime is not supported |
Beta Was this translation helpful? Give feedback.
-
Module Federation: The Biggest Update Since Its Inception
Four years after its creation, Module Federation is receiving its most significant update yet. But why redesign Federation?
Let's dive in.
Webpack Users can use the Webpack Plugin
Rspack users, its built into 0.5.0
The Need for Redesign
The introduction of Rspack necessitated a simpler way to maintain support across various bundler tools. To achieve this, we separated Module Federation from Webpack and implemented its runtime as a library. This move liberated federation from a significant portion of bundler lock-in.
Essential Components
The key components of this system include:
These components might seem overwhelming, so we've made it easier for you. You can use
@module-federation/runtime-tools
as a comprehensive package. It exports several of the underlying package exports in a user-friendly way, making it easier to work with, less to worry about synchronizing upgrades of various parts.runtime-tools
can also be used in Rspack to override the default @module-federation/* packages that come with rspack. This allows users to upgrade module federation partially without needing to update the rspack core.The "Federation Runtime"
Contributing to webpack plugins can be daunting due to its steep learning curve which often becomes a discouragement for community contribution. To overcome this challenge, we have shifted the federation runtime to a library. This shift reduces the need for bundler-specific knowledge, making our runtime much more user-friendly and accessible for community expansions and contributions.
The main runtime code that makes module federation what it is has been decoupled from the "bundler runtime" parts. Federation is implemented into bundlers like webpack and rspack by providing bindings for the runtime and initializing it.
Other tool chains could support module federation in a consistent manner if they are able to provide the bundler runtime bindings needed to initialize the runtime.
The "FederationHost" Instances
What is a
FederationHost
? Each container/runtime is an instance ofFederationHost
. The "host" application, as we know them, is usually the first FederationHost in the instances. FederationHost is the class that provides additional capabilities (like runtime plugins, hooks, lifecycles, and utilities). We have added a global object that allows you access to all instances:globalThis.__FEDERATION__
. If you log this (be it client or server), you should see something like:This data and more can be accessed via our runtimePlugins APIs as well. In the future, we will expand on the data one has access to.
Runtime Plugins
This is one of the most exciting additions to this initial update. Runtime plugins invert control. At ByteDance, we have many complex requirements and needs for Module Federation. Nearly all of these fell far beyond the scope of what the original plugin was designed to accomplish.
Runtime Plugins were designed to allow us and the community to extend module federation. It introduces the concept of hooks and a lifecycle, something sorely missed in the original plugin design.
Here are the hooks we currently have:
You can read more in-depth about these hooks here.
Here is an example of a runtimePlugin.
You can find more examples:
https://github.com/module-federation/module-federation-examples/tree/master/runtime-plugins
https://github.com/module-federation/universe/tree/main/apps/runtime-demo
And general Readmes:
https://github.com/module-federation/universe/tree/main/packages/enhanced
https://github.com/module-federation/universe/tree/main/packages/runtime
This specific one is currently what is used in nextjs-mf:
Community plugins are welcome, and we will provide handy runtimePlugins for common use cases over time. For example, a "retry-runtime-plugin" would be great to provide to the community as an off-the-shelf package.
Future-Proofing our Runtime
Our runtime can be implemented and other tools only need to create the right bindings, making runtime interfaces consistent for everyone. This reduces friction and fragmentation around federation. Bundler teams could support the federation by providing "bundler runtime" packages or bindings.
The Federation plugin uses a significant amount of graph data to create its containers. Using JS hooks to expose this data to a Javascript plugin would create performance problems. It was best implemented in Rust, which meant that we would require a more robust user API to customize how it works, as native code must be compiled into rspacks core.
During the redesign, we focused on:
Future Plans
Beta Was this translation helpful? Give feedback.
All reactions