Micro Frontends Step by Step Using React, Webpack 5, and Module Federation With Deployment to AWS
Rany ElHousieny, PhD???
Senior Software Engineering Manager (EX-Microsoft) | Generative AI Leader @ Clearwater Analytics | Generative AI, Conversational AI Solutions Architect
In this article, I will go step by step in creating two Micro Frontend React Components and render a Button component from one into the other. At the end of this article, you will be able to implement a microfrontend component and render it into a microfrontend container, then deploy it to AWS with a secured domain. The final result can be seen at https://mfe1.microfrontends.info/
If you are new to Microfrontend, you may start with the following article:
This hands-on example is a continuation to the following two articles where I explained how Micro Frontends work with Webpack5 and Module Federation. I wanted to give clean steps on React components without all the explanations. Please, refer to those articles for explanations
The final project can be found at https://github.com/ranyelhousieny/react-microfrontends
Video for the project at
==========================
1. Create two React apps and install dependencies
npx create-react-app mfe1
cd mfe1
yarn add webpack webpack-cli webpack-server html-webpack-plugin babel-loader webpack-dev-server
npx create-react-app mfe2
cd mfe2
yarn add webpack webpack-cli webpack-server html-webpack-plugin babel-loader webpack-dev-server
Note: While I used create-react-app here for an easier walkthrough, I will not depend on it at all and we will create our own webpack.config.js. You may learn how to set up a React project without CRA in this article
2. In both Apps, rename index.js to bootstrap.js
in bootstrap.js, Remove the imports to index.css and reportWebVitals and keep the file as shown below:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById(
'root'
)
);
Here are the files on Github
We do this step to make bootstrap load asynchronously. It is needed for MFE2 to wait for Webpack to fetch components from MFE1.
3. In both Apps, create a new index.js that has one line
import('./bootstrap');
Here is the file on Github
4. In MFE1, Create. a Button component
Create a file src/Button.js
Copy inside it this code (It is a very simple component)
import React from 'react';
const Button = () => (
<button>MFE1 Button</button>
);
export default Button;
Code can be found at
4.1. In MFE1, update App.js as?follows
Code can be found at https://github.com/ranyelhousieny/react-microfrontends/blob/main/mfe1/src/App.js
5. In MFE1, Create a Webpack.config.js on the root and put the following inside it
(details about this file and building it step by step can be found?here ?https://www.dhirubhai.net/pulse/understanding-micro-frontends-webpack5-configurations-rany/ ?and the video?https://youtu.be/AZDDIgJSKU0 )
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
mode: 'development',
devServer: {
port: 8083,
},
module: {
rules: [
{
/* The following line to ask babel
to compile any file with extension
.js */
test: /\.js?$/,
/* exclude node_modules directory from babel.
Babel will not compile any files in this directory*/
exclude: /node_modules/,
// To Use babel Loader
loader:
'babel-loader',
options: {
presets: [
'@babel/preset-env' /* to transfer any advansed ES to ES5 */,
'@babel/preset-react',
], // to compile react to ES5
},
},
],
},
plugins: [
new ModuleFederationPlugin(
{
name: 'MFE1',
filename:
'remoteEntry.js',
exposes: {
'./Button':
'./src/Button',
},
}
),
new HtmlWebpackPlugin({
template:
'./public/index.html',
}),
],
};
Here we created MFE1 and made it expose the Button Component through https://localhost:8083/remoteEntry.js. Webpack renders this on https://localhost:8083.
领英推荐
6. In MFE2, Create a Webpack.config.js on the root and put the following inside it
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
mode: 'development',
devServer: {
port: 8082,
},
module: {
rules: [
{
/* The following line to ask babel
to compile any file with extension
.js */
test: /\.js?$/,
/* exclude node_modules directory from babel.
Babel will not compile any files in this directory*/
exclude: /node_modules/,
// To Use babel Loader
loader:
'babel-loader',
options: {
presets: [
'@babel/preset-env' /* to transfer any advansed ES to ES5 */,
'@babel/preset-react',
], // to compile react to ES5
},
},
],
},
plugins: [
new ModuleFederationPlugin(
{
name: 'MFE2',
filename:
'remoteEntry.js',
remotes: {
MFE1:
'MFE1@https://localhost:8083/remoteEntry.js',
},
}
),
new HtmlWebpackPlugin({
template:
'./public/index.html',
}),
],
};
Here we just said that MFE1 exposed components can be available in MFE2 remotely through https://localhost:8083/remoteEntry.js
7. In MFE2 src/App.js import Button (Lazy import)
const MFE1_Button = React.lazy(
() => import('MFE1/Button')
);
Add it to the App as follows
function App() {
return (
<div>
<h1>MFE2</h1>
<div>
<React.Suspense fallback='Loading Button'>
<MFE1_Button />
</React.Suspense>
</div>
<h2>MFE2</h2>
</div>
);
}
open a terminal inside MFE1 directory and run
yarn webpack serve
Do the same on MFE2 directory
Now open the browser and navigate to
You should see the following
==============================
Explanation:
Now, let's take a step back and understand what we have done.
First: Webpack created two servers for us
Second: Using Module Federation Plugin we exposed the Button component from MFE1 site (https://localhost:8083/) and imported it into MFE2
Here is the configuration that did that
=======================
Deploying Microfrontends
After we implemented and tested the Microfrontends locally, let's deploy them to AWS. Follow the steps in the following article to deploy to AWS:
You can browse the deployed version at https://mfe1.s3-website-us-east-1.amazonaws.com/
If you click inspect and then Network as shown above, you can see the call to get https://rany.tk/mfe/mfe1/dist/remoteEntry.js
Now, we created a host and added a microfrontend inside it then we deployed to AWS.
========================================
Add AWS CloudFront
after deploying to S3, let's add CloudFront for caching, security, and to add a domain name. This is a very important step when deploying a website. Follow the following article to add CloudFront
Now, you can access MFE2 from the following Link https://d1tsn16diydefl.cloudfront.net/
=====================================
Purchasing and Adding a Domain name:
Now, it is very hard to memorize the previous link https://d1tsn16diydefl.cloudfront.net/ . In the following article I will go step by step to purchase microfrontends.info and render the site to https://mfe1.microfrontends.info/
Other Micro Frontend articles at:
NodeJs, ExpressJs, ReactJs, PostgreSQL-FULL STACK DEVELOPER
1 年this artical not complete support. I will give you 2 star
Programmer at FizzDev
3 年Hello! I'm a bit stuck with this article. I can't understand how to use my modules in container app? Can you give some explanations with this?