Webpack Federation can do quite a lot, but orchestrating it can sometimes be a little messy or complex with its given api. The idea is to offer some additonal lifecycles directly on webpack interfaces to allow for pluggability and a more standardized ecosystem
new ModuleFederationPlugin({
remotes: {
app1: {
middleware: [
(importValue)=> {
return getEnvVars() // async promise that injects env vars into document before webpack attempts to connect remote
},
(importValue) => {
if(window.remoteOverrides['app1']) {
// if an override exists, change the script that will be injected.
return window.remoteOverrides['app1'] // --> otherRemote@http://otherUrl
} else {
return importValue // do nothing
}
}
],
onBeforeGet: [
async (container)=>{
await container.get('./sentry-hub-register'); // load an exposed module before responding to the desired get request in the codebase
},
async (container,request)=> {
const allowed = await checkIfAllowed();
if(allowed) {
return request // import("app1/admin") would have a request of "./admin"
} else {
return './not-authorized'
}
}
]
import: 'app1@http',
remoteType: "var" // standard webpack feature
}
}
});
promise new Promise
is handy, but it would be great if one could compose a series of middlewares into the promise chain in a standard manner.
This would be useful for
- controling versions/overrides at runtime
- injecting env variables before webpack connects the containers together
- doing some series of actions during the initial import() for a remote that only happens once - prior to a remote being injected
- additional security or auth gates without having to write wrapper code around your exposed modules.
The lifecycle of federation is as follows.
- inject remote (happens once)
- init() remote (happens once)
- get() exposed module (happens for every import)
After middleware has been run, and the remote container injected into the application, and has initialized.
Sometimes i might want to do something before calling the underlaying get() of a container. perhaps re-route the module request, or set up distributed logging automatically before import() resolves and starts executing.
onBeforeGet is basically middleware but for the module import itself instead of container injection
Prop | Description |
---|---|
moduleMap | list of all available modules from a single remote. |
remoteMap | list of all remotes available for consumption |
remoteUrlMap | list of all remotes URL to initilize |
const ModuleFederationEnhacedPlugin = require("@module-federation/ModuleFederationEnhacedPlugin");
module.export = {
//... rest of your config
plugins: [
new ModuleFederationEnhacedPlugin({
name: "myApp",
library: { type: "var", name: "app2" },
filename: "remoteEntry.js",
remotes: {
app1: "[email protected]/remoteEntry.js",
app2: "[email protected]/remoteEntry.js",
},
exposes: {
Button: "./src/Button",
Input: "./src/Input",
/* Auto Generated:
moduleMap: ['Button', 'Input'],
remoteMap: ['app1', 'app2'],
remoteUrlMap: [{app1: 'myApp1.com/remoteEntry.js' app2: 'coolAppRunningOnCLoude.com.br/remoteEntry.js'}]
*/
},
}),
],
};
At the component:
import moduleMap from "myApp/moduleMap";
import remoteMap from "myApp/remoteMap";
import remoteUrlMap from "myApp/remoteUrlMap";
Prop | Description |
---|---|
chunkMap.json | list of all chunkNames and create a json file on dist folder. |