Sitemap
Nerd For Tech

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/.

Understanding Micro Frontends With a Hands-On Example Using React, Webpack 5, and Module Federation

12 min readFeb 8, 2021

--

Press enter or click to view image in full size

Micro Frontends have been growing, recently, because of the need to break the Frontend monolith and the success showed in Microservices architecture. However, very few understand the concept or know that it exists. Reading about theoretical concepts makes things harder than they are. Therefore, I decided to explain the concepts with a hands-on project. I love to see things working to understand challenges and how things work. I will be using Webpack 5 and Module Federation Plugin. I hope this is useful for you. As usual, please send me your feedback.

Good frontend development is hard. Scaling frontend development so that many teams can work simultaneously on a large and complex product is even harder.” Martin Fowler

Setup The Development Environment

Prepare your machine and install nodejs, if needed follow the article/video, below:

[Optional] You may create a Github project and clone it (I am using https://github.com/ranyelhousieny/micro-front-ends)

git clone https://github.com/ranyelhousieny/micro-front-ends.git

Press enter or click to view image in full size

We will create the following 3 frontends container, micro-front-end-1, and micro-front-end-2

We will use create-react-app to create the 3 base projects as explained in the video, below, but we will call them container, micro-front-end-1, and micro-front-end-2, instead.

The container will orchestrate between multiple micro-front-ends

Press enter or click to view image in full size

npx create-react-app container

Press enter or click to view image in full size

npx create-react-app micro-front-end-1

npx create-react-app micro-front-end-2

Install dependencies for micro-front-end-1

cd micro-front-end-1

npm install webpack webpack-cli webpack-server html-webpack-plugin

Press enter or click to view image in full size

npm install webpack webpack-cli webpack-server html-webpack-plugin webpack-dev-server

Implement micro-front-end-1

go inside the micro-front-end-1 directory and open the IDE using (code .)

Navigate inside src/index.js

remove all the code in index.js and replace it with

console.log(“micro-front-end-1”);

Press enter or click to view image in full size
Press enter or click to view image in full size

Use Webpack to bundle the code

A detailed explanation of Webpack configurations can be found in the following article

Let’s create a bundle using Webpack

Create webpack.config.js on the root of the micro-front-end-1

touch webpack.config.js

Now, let’s try to build and see what happens. Run the following command:

npm webpack

You will get few errors. Let’s take one by one.

Press enter or click to view image in full size

The first error is asking about the mode. Webpack needs to know which mode to run with to be able to bundle the dependencies, accordingly. Let’s use Development mode. In webpack.config.js add the following

module.exports = {
mode: 'development',
};
Press enter or click to view image in full size

This will take care of the first error and tell Weboack to build in development mode. Now, build again and watch the folders on the left hand side. You will notice a destination folder named “dist” will be created.

Press enter or click to view image in full size

This is the folder that will be generated by Webpack’s build and bundle process and this is the folder we will deploy to the S3 Bucket. What happened here is that Webpack took all the code we have index.js, bootstrap.js, App.js … and there dependencies and bundled them in main.js as you can see.

Now we do not see the mode error, but we still React and loader errors. Those errors because Webpack needs loaders to understand React. As you know Browser only understand CSS, HTML,, and JavaScript ES5 (for now). JSX and ES6+ will need a compiler. We use babel for that. I will show you how to add those loaders to the configuration but first let’s create a local server to see our demonstrate our website (This will be S3 configured as a website at the end)

add a script to package.json

Press enter or click to view image in full size
Press enter or click to view image in full size

A new file will be created dist/main.js

Press enter or click to view image in full size

Add the Webpack server

To add a local server on a certain port (here, I used 8001), add the following lines to webpack.config.js

devServer: {
port: 8081,
},
Press enter or click to view image in full size

Now, run the following command

yarn webpack serve

This will start a local web server on port 8081. However, if you navigate to https://localhost:8081, you will only find alist of files. This is because we did not configure index.html, yet. We will do this in the coming step. However, try to browse main.js and you will be able to see its content as follows:

Press enter or click to view image in full size

So far, Webpack created a local web server on Port 8081 as we configured it in Webpack.config.js. However, it is still missing a min component for the browser: index.html

HTML Webpack Plugin

We need to import html-webpack-plugin for Webpack to generate index.html and add the bundled js files to it.

const HtmlWebpackPlugin = require('html-webpack-plugin');

Also, add the html-webpack-plugin to fill the index.html as follows

Press enter or click to view image in full size

webpack.config.js up to this step can be found here

Add serve to the script in package.json

Press enter or click to view image in full size

remove everything in public/index.html and write the following

Press enter or click to view image in full size

from the terminal under the directory of micro-front-end-1, start the script

npm run webpack

Go to the browser and browse HTTP://localhost:8081

right click and inspect to see the output of the console.log

Press enter or click to view image in full size
Press enter or click to view image in full size

This is the main concept.

Now, let’s display on the page, instead of console

Add the following to index.html

<div id=”root”></div>

Press enter or click to view image in full size

Add the following querySelector

document.querySelector(‘#root’).innerHTML = `<h1>Micro-Front-End-1</h1>`

Press enter or click to view image in full size

Refresh the browser

Press enter or click to view image in full size

So far, we have one component and it is not connected to anything

Press enter or click to view image in full size

=====================================

Now, let’s build the container

open another terminal and navigate to the root directory where we had the three apps

Press enter or click to view image in full size

Now, navigate inside the container directory

Press enter or click to view image in full size

Install dependencies as before.

install webpack webpack-cli webpack-server html-webpack-plugin

Press enter or click to view image in full size

Now, let’s navigate back to the root of the three services and open VS code with the three components to work on them at the same time

Press enter or click to view image in full size

Copy webpack.config.js from micro-front-end-1 to container and change the port to be 8080 as follows

Press enter or click to view image in full size

Change the package.json script the same way we had before (you can copy it from micro-front-end-1

“webpack”: “webpack serve”,

Press enter or click to view image in full size

Change index.js and index.html like before but write to the console “container”

Press enter or click to view image in full size

run the script (npm run webpack) and check the browser http://localhost:8080/

Press enter or click to view image in full size

========================

Connecting Both together

1- Add Module Federation Plugin

in micro-front-end-1/webpack.config.js add the following

Press enter or click to view image in full size

This will expose index.js from micro-front-end-1. (Note that we used camelCase)

Now, let’s fetch it from the container

Go to container/webpack.config.js and add the following

Press enter or click to view image in full size

container/webpck.config.js up to this point can be found here

now, rename container/src/index.js to container/src/bootstrap.js and import microFrontEnd1/MicroFrontEnd1Index (This is to run the file asynchronously until it gets the data from micro-front-end-1 to the container)

Press enter or click to view image in full size

create a new container/src/index.js and import(‘./bootstrap’);

Press enter or click to view image in full size

Now restart npm run webpack for both services

First, run micro-front-end-1

ctrl + c

npm run webpack

Press enter or click to view image in full size

Second, run the container

ctrl + c

npm run webpack

Press enter or click to view image in full size

Add the id to container/public/index.html

Press enter or click to view image in full size

Browse the container port 8080 http://localhost:8080/ and you will find the text from micro-front-end-1 present there

Press enter or click to view image in full size

Now, let’s understand what we have done.

As you are on the page, select Network, Disable Cache, and Java as shown below:

Press enter or click to view image in full size

Refresh the page to send calls to servers and note the output

Press enter or click to view image in full size

Right-click on the header next to Name and select Url from the menu to show the URL that has been called.

Press enter or click to view image in full size

You will see the following URLs been calls

Press enter or click to view image in full size
  1. It first called main.js on http://localhost:8080/main.js . This is the container
  2. Called the remoteEntry.js on http://localhost:8081/remoteEntry.js . This is micro-front-end-1
  3. Back again to the container calling bootstrap
  4. finally calling src_index_js.js from micro-front-end-1 (index.js) to present its output on the screen

All of this came from the ModuleFederationPlugin

Press enter or click to view image in full size

webpack used this configuration from micro-front-end-1/webpack.config.js to create http://localhost:8081/remoteEntry.js and http://localhost:8081/src_index_js.js

Then the configuration on container/webpack.config.js told the server how to fetch http://localhost:8081/remoteEntry.js

Press enter or click to view image in full size

inside http://localhost:8081/remoteEntry.js the information needed to fetch src_index_js.js

Module Federation Plugin allowed JavaScript to dynamically import code from micro-front-end-1 into the container at runtime.

==============

Adding the second Micro Frontend

Before adding the second Micro Frontend, let’s add more paragraphs to the first one. I like using a tool called Lorem ipsum

Press enter or click to view image in full size

You just press F1 and write Lorem ipsum and select how many paragraphs

The new index.js for this step can be found here

Now, repeat the same processes inside micro-front-end-2

  1. Copy webpack.config.js from micro-front-end-1 to micro-front-end-2
  2. Update the names inside it as follows:
Press enter or click to view image in full size

Install dependencies for micro-front-end-2

cd micro-front-end-2

npm install webpack webpack-cli webpack-server html-webpack-plugin

Press enter or click to view image in full size

Add the webpack script to package.json

Press enter or click to view image in full size

run npm install from inside micro-front-end-2 folder

Press enter or click to view image in full size

Erase the content of micro-front-end-2/public/index.html and copy into it micro-front-end-1/public/index.html content. replace the id with a new id as follows

Press enter or click to view image in full size

Erase the content of micro-front-end-2/src/index.js and copy into it micro-front-end-1/public/index.html content. replace the id with the one you had above and the name of the service in the <h1> tag as follows

Press enter or click to view image in full size

Now, run npm run webpack

Press enter or click to view image in full size

Now navigate to http://localhost:8082/

Now, connect it to the container

in container/webpack.config.js add another remote as follows

microFrontEnd2: ‘microFrontEnd2@http://localhost:8081/remoteEntry.js',

Press enter or click to view image in full size

in container/src/bootstrab.js add the following import

import ‘microFrontEnd2/MicroFrontEnd2Index’;

Press enter or click to view image in full size

in container/public/index.html add the id for micro-front-end-2 in the space you want. I added it as follows

Press enter or click to view image in full size

restart webpack for the container and navigate to http://localhost:8080/

Press enter or click to view image in full size

No, if you inspect the network traffic you will find calls to both servers

Press enter or click to view image in full size

=================================

So far, we have not used React. In the following article, we will add a third micro frontend, react-microfrontend-3

Press enter or click to view image in full size

Learn More

--

--

Nerd For Tech
Nerd For Tech

Published in Nerd For Tech

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/.

Rany ElHousieny
Rany ElHousieny

Written by Rany ElHousieny

https://www.linkedin.com/in/ranyelhousieny Software/AI/ML/Data engineering manager with extensive experience in technical management, AI/ML, AI Solutions Archit

Responses (4)