React Micro Frontends with Webpack's Module Federation
Tags: webdev, microfrontends, webpack, react
Published: 2021-12-21 05:39:29


**Micro Frontends** is a very popular topic in today's frontend world. Most of the teams tend to adopt this micro frontend strategy to develop their large and complex web applications, due to many advantages it provides such as, 

- Separate, decoupled codebases
- Independent deployment
- Incremental updates 

Below diagram showcases some of the important concepts of micro frontends. 

![Micro Frontend Concepts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqtkmjvvel08cyhlsgg2.png)

Most popular way of developing micro frontends is using HTML5 Web Components (Custom Elements). Angular like web frameworks has [extended to support Web Components](https://angular.io/guide/elements), while most of other libraries like [React, supports it](https://reactjs.org/docs/web-components.html) out of the box.

For more information about micro frontends you can refer to 

- https://martinfowler.com/articles/micro-frontends.html
- https://micro-frontends.org

## What is Module Federation in Webpack ? 

Webpack version 5 comes with a new feature called [Module Federation](https://webpack.js.org/concepts/module-federation/), which helps to share code and dependencies between projects at runtime. 

In high level, an application `exposes` certain component/s via a separate javascript file, and other application that wishes to use that component, async loads that `remote` javascript file and consume that component. 


![Webpack's Module Federation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hyv0byoa6dbhv5517430.png)

Recent times this feature has changed the way we develop micro frontends. 

In this post, I will walk through how you can develop React based micro frontends using Webpack's Module Federation by creating a simple bank application that shows a list of accounts and account details on a selected account. 

This is how our final application architecture would look like. 

![Simple Bank Application using React](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mlti5tc8dbz732kzw088.png)

## Let's get started..

All of the code in this post can be found [here](https://github.com/PahanPerera/react-webpack-micro-frontends) for your references. 

### Prerequisites 

First of all, since this is about React and webpack, you should have a React application configured with Webpack.

Refer to [this project](https://github.com/PahanPerera/react-webpack-micro-frontends/tree/main/account-summary-app) if you need help doing that. 

Also, as mentioned above, we will need three React projects for our application

- `accounts-summary-app` - Micro frontend that provides the summary of all the accounts 
- `account-details-app` - Micro frontend that provides details of a selected account
- `main-app` - app that hosts above two components. Also acts as a medium to communicate with each other. 

### Configure `ModuleFederationPlugin` in Micro Frontend Projects

`ModuleFederationPlugin` is a [high level webpack plugin](https://webpack.js.org/plugins/module-federation-plugin/) that provides a very convenient way to configure module federation in your projects. Also plugin comes along with webpack library without need of installing another dependency as well.


Responsibility of our micro frontend projects is to `expose` a component. So let's add following to `webpack.config.js` of `accounts-summary-app` project. 

import the plugin
```js
const { ModuleFederationPlugin } = require("webpack").container;
```

configure the plugin
```js
  plugins: [
    new ModuleFederationPlugin({
      name: "AccountsSummaryApp",
      filename: "accountsSummaryApp_remote.js",
      exposes: {
        "./AccountsSummary": "./src/components/AccountsSummary",
      },
    }),
    ...
  ],
```
- `name` is unique identification of your module. Normally this is the name of your micro frontend project. 
- `filename` is the name of the javascript file that exposes the components
- `exposes` is a map (key and a value) of components that are exposed from this module. (key will act as an alias for the component while the value is where the component located in the project)

Now, let's run this project locally and see what happens. 


![Separate javascript file for exposed module](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghnm55s4zlr57eygmxd8.png)

As you can see, now webpack has bundled our `AccountsSummary` component into a separate javascript file, as we instructed in the webpack configuration. 

Let's do the same to the `account-details-app` project as well

```js
  plugins: [
    new ModuleFederationPlugin({
      name: "AccountDetailsApp",
      filename: "accountDetailsApp_remote.js",
      exposes: {
        "./AccountDetails": "./src/components/AccountDetails",
      },
    }),
    ...
  ],
```


In case you missed some thing, you can always refer to these two projects 

[accounts-summary-app](https://github.com/PahanPerera/react-webpack-micro-frontends/tree/main/account-summary-app)
[account-details-app](https://github.com/PahanPerera/react-webpack-micro-frontends/tree/main/account-details-app)

### Configure `ModuleFederationPlugin` in Host App project. 

Like I was explaining before, our host app, `main-app` is responsible for loading the components from micro frontend projects.

Like micro frontends configurations defines `exposes`, Host app's webpack configuration defines `remotes` that tells webpack where to find those external components. 

```js
  plugins: [
    new ModuleFederationPlugin({
      remotes: {
        AccountsSummaryApp_Remote: "AccountsSummaryApp@http://localhost:9001/accountsSummaryApp_remote.js",
        AccountDetailsApp_Remote: "AccountDetailsApp@http://localhost:9002/accountDetailsApp_remote.js",
      },
    }),
    ...
  ],
```
`remotes` is a map (key and value) that defines all the external modules that it consumes. Key will act as an alias for the module and value defines the remote javascript file location for that module. 

value should have a special format like below

`<Name of the Exposed Module>@<Remote URL of the javascript file>`

Now that all the webpack configurations are completed, let's write some javascript code to load external components.

### Load External Components to Host App

One of the beautify thing about this webpack module federation is that, developers can not feel a difference between importing a local component from its own project and remote component from an external javascript file. 

React code will look like you are lazy loading a component.

```js
const AccountsSummary = React.lazy(() =>
  import("AccountsSummaryApp_Remote/AccountsSummary")
);
```
and use that in your jsx
```jsx
<Suspense fallback={<h1>Error while loading Account Summary</h1>}>
  <AccountsSummary onAccountSelected={handleAccountSelected} />
</Suspense>
```
One thing to note about the import is that to use same alias that you define in the host application along with the component alias that you defined in your micro frontend project


![Module Federation configurations](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3iepl3jvw4wd6cc03gkx.png)

### Communication between components

As mentioned earlier, external components are same as local components in your project. So standard ways of communication should be applicable here as well.

For this application, I have defined a shared state with in the host application and each component communicate via that shared state. 

Refer to `main-app` to see the [code](https://github.com/PahanPerera/react-webpack-micro-frontends/blob/main/main-app/src/pages/AccountsPage.js).


## Conclusion 

This is very beginner level tutorial about how to develop Micro Frontends using Webpack's Module Federation feature. During this post I was able to briefly explain about
- What are Micro Frontends
- What is Webpack's Module Federation Feature
- Configure Micro frontends to expose components
- Configure Host app to use those exposed components
- How to communicate between components

Full working example can be found [here](https://github.com/PahanPerera/react-webpack-micro-frontends).

You can find the full React Template used in this sample bank application [here](https://pahanperera.gumroad.com/l/GDJBq). 

That is all for now. Please share you feedbacks. Thank you for reading.