Micro Front-End: Module Federation
What is Module Federation?
To understand Module Federation, we need to first know some basics of webpack: Webpack Basics
Now that we know that webpack
- bundles all the source files
- the bundled files sits in a /dist folder (or as configured in webpack.config.js)
- We need to add plugins if we need to bundle HTML files
- We need to add "rules" if we need to bundle CSS files
- Just like how we had to add a special plugin to bundle HTML files, we also need a special plugin for Module Federation
Basic idea behind Module Federation
- An app can have multiple "micro apps". Each containing its own "package.json".
- Each of these apps run on their own in their own port.
- These apps can still share some code and talk to each other.
- To summarize, each of these apps can expose certain modules and consume certain modules
- They share these modules at runtime. They don't depend on the contents of the "dist" folder
EXAMPLE
In each of these folders
- Create a blank HTML, JS, webpack.config.js files in each of these folders
- npm init -y
- npm install --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin
- In package.json file add a new script => "build": "webpack"
Contents that go in these files
In both the index.html files
<!DOCTYPE html>
<html>
<head></head>
<body>
<script src="bundle.js"></script>
</body>
</html>
remote-app\remoteModuleIndex.js
//A simple Module that exposes a function
export function remoteModuleGreet() {
return "Hello from remote module!";
}
import("remoteApp/Module").then((module) => {
document.body.innerHTML = module.remoteModuleGreet();
})
Finally comes the WebPack config.
- Host app consumes the remote module dynamically.
- Remote app exposes remoteModuleIndex.js as ./Module
host-app\webpack.config.js
const path = require("path");
const { ModuleFederationPlugin } = require("webpack").container;
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: "development",
entry: "./index.js",
output: {
publicPath: "http://localhost:8080/",
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new ModuleFederationPlugin({
name: "hostApp",
remotes: {
remoteApp: "remoteApp@http://localhost:8081/remoteEntry.js",
},
}),
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html'
})
],
devServer: {
port: 8080,
host: "0.0.0.0",
static: path.join(__dirname, "dist"),
},
};
remote-app\webpack.config.js
const path = require("path");
const { ModuleFederationPlugin } = require("webpack").container;
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: "development",
entry: "./remoteModuleIndex.js",
output: {
publicPath: "http://localhost:8081/",
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
plugins: [
new ModuleFederationPlugin({
name: "remoteApp",
filename: "remoteModuleIndex.js",
exposes: {
"./Module": "./remoteModuleIndex.js",
},
}),
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html'
})
],
devServer: {
port: 8081,
host: "0.0.0.0",
static: path.join(__dirname, "dist"),
},
};
Now, host app runs on http://localhost:8080/
Remote app runs on http://localhost:8081/
Finally in both the apps, run
- npm i
- npm run build
- npx webpack serve --mode development
Comments
Post a Comment