Micro Frontends using React, Module Federation, Webpack 5
Tags: react, microservices, javascript, frontend
Published: 2023-04-11 21:48:50

## Micro Frontends


Extending the microservices idea to front end development. In the current trends, most of the application are migrating based on microservices architecture. In Microservice architecture, each feature or business is developed by independent teams and each team specialises in their respective feature and develops end-end.


Monolith web applications sits on top of microservices which is a single page application develops all the features. Gradually application grows and team faces difficulty to maintain the entire application. Alike Microservices, design the same pattern from frontend and it is named as Micro Frontends, thought has come in the late 2016 by the Thoughtworks.

Now Web application can maintain by independent teams for end-end development on each feature or business or module without knowing what other module does.

## Module federation

New method of sharing code between frontend applications which makes code more straight forward and more independent. **Module** **federation** is one of the exciting features in Javascript architecture used in Webpack 5, loads code dynamically at runtime to reduce code duplication and host application loads only missing dependencies. It is one of the best ways to design the application in Microservice approach. And it has many benefits to web application if utilized appropriately.

## Alternatives

For Micro Frontends design, there are many other alternatives:

- Bit
- Single-SPA
- SystemJs 
- And many more ways to design the Micro Frontends.

Module Federation is not a framework, it is a plugin that is added to Webpack, which gives you freedom and flexibility to build your project the way you want and also offers developers to choose the technology they want to use. It integrates components at runtime. 

## Module Federation Configuration

It is very easy to integrate Module federation within the application. It has two main concepts:

- **Remote Federated Module**: Expose the components you want to share in Webpack.config.js

- **Container Federated Module**: Consume and Render the exposed components by the Remote Federated Module.

## Step by Step

Create two react applications, one for host (Shop-container) and other for remote(product) using below command

+ Shop-container
```
npx create-react-app shop-container
```

+ Product

```
npx create-react-app product
```

Install Webpack in both applications

```
npm i webpack webpack-dev-server webpack-cli css-loader 
html-webpack-plugin sass sass-loader style-loader url-loader 
@babel/core @babel/preset-env @babel/preset-react 
babel-loader -D
```

Import Module Federation plugin as below

```
const ModuleFederationPlugin = 
require("webpack/lib/container/ModuleFederationPlugin");
const dependencies = require("./package.json").dependencies;
```

Create webpack.config.js file under root folder of Product application and plugin module federations

- **Product application**

```
plugins: [
        new HtmlWebpackPlugin({
            template: "src/index.html",
        }),
        new ModuleFederationPlugin({
            name: "product",
            filename: "remoteEntry.js",
            remotes: {},
            exposes: {
                './App': './src/App.js',
            },
            shared: {
                ...dependencies,
                react: {
                    singleton: true,
                    requiredVersion: dependencies.react,
                },
                "react-dom": {
                    singleton: true,
                    requiredVersion: dependencies["react-dom"],
                },
            },
        })
    ]
```

Under **ModuleFederationPlugin**, few of the properties which are common in use

- **exposes**: property is to expose the component which you want to share. If you share root components, all components will be loaded and route works the way it is.

- **shared**: It is to include packages you needed when using this remote application. Suppose say, if you have angular as host/container application, remote is based on react, then it is where you include react packages to load the application. There are many benefits under the hood. some of them are singleton, avoid duplicate packages, loads missing packages and so on.

- **filename**: This plugin generates file with the name mentioned here and renders the file dynamically at runtime.

Similarly create webpack.config.js file under root folder of Shop-container application and plugin module federations.

```
plugins: [
        new ModuleFederationPlugin({
            name: "shop-container",
            remotes: {
              product: "product@http://localhost:4500/remoteEntry.js"
            },
            exposes: {},
            shared: {
              ...dependencies,
              react: {
                singleton: true,
                requiredVersion: dependencies.react,
              },
              "react-dom": {
                singleton: true,
                requiredVersion: dependencies["react-dom"],
              },
            },
          })
    ]
```

- **remotes**: It is to mention all remote applications url along with filename. Here, shop-container application consumes Product application.

Now import product component and render the remote content as below

```
import Product from 'product/App';

const App = () => {
  return (
    <>
      <Header></Header>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/products" element={<Product />} />          
      </Routes>
      <Footer></Footer>
    </>
  );
}

export default App;
```

use key name which mentioned in remotes property inside webpack.config.js and import the component name.

` import Product from 'product/App';`

and use the component

Below are the screeshots of container and remote applications

- product application

![Product Application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5tiyj3p75bujek6ynh4f.png)

- Shop-container Application

![Shop Container Application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v6yq5qov8rszn5o1bhey.png)


For Reference, complete source code is in below repository
[https://github.com/sandeep0515/microfrontends-react]


We can create independent repositories for each application, containerized the applications separately and maintain the code easily.

Happy coding!