Setup Micro Frontend Application with React Js
Tags: javascript, webdev, beginners, react
Published: 2022-04-24 17:41:59

In this article we are going to setup a micro frontend application with well known CLI tool "create-mf-app" which is a bootstrap tool to setup Module Federation.
 
## What is Micro Frontend?🤨
Micro-frontend designs break down a front-end application into little, semi-independent "microapps" that work together loosely. This can aid in the management of complex projects.

## Setting up project
Now we are going to setup a project which contains two micro frontends and one container app which will hold the all micro frontend apps.
In this article we are focusing on only setting up project in React js only but we can have multiple framework.

Open a cmd/terminal where you are going to setup project and enter below command.

```
npx create-mf-app
```
If create-mf-app is already installed then it will directly prompt for application name and if not then it will ask to install it just simply enter 'y' and it will install it for you.

Once create-mf-app is installed, it will ask for the following info.

![create-mf-app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rt7y4mqjktys0ttzejv.png)

I created a Shell app and given port 3000 to run the application.

Lets create another micro app with name 'common-components-lib'
We will follow same step as above but just different port and name.

![common-components-lib](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/snwceqnqxhu09rw1vlsv.png)

I created a Shell app and given port 3000 to run the application.

Now you need to move inside of each app and enter below command to build and run the app.
`npm install && npm start`

I recommend to open these 2 apps in two different cmd/terminal.

![npm-install](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vlau0zwyndg797tnj845.png)

I created a common-components-lib app and given port 3001 to run the application.

Our basic idea behind creating these 2 app is that Shell will be our container for all the micro apps and common-components-lib will contains common components like Header, Footer, etc.

We will now open Folder in a Code editor. Mine Favorite editor is Visual Studio Code❤ but you can use code editor of your choice.

After opening it, your folder structure will look like this.

![folder-structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0kdflpob5gh5plu9pui.png)

Note: make sure both apps are up and running on different ports.

![app-preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gohndtau3gur7uhbctmb.png)


![app-preview-common](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wonhaevwywigfzrokea4.png)

## Creating Components inside micro app
Now lets add one Header and Footer Component inside the common-components-lib app.

Create a Header Component and paste below code.

```
import React from 'react';
import './header.css';

function Header() {
  return (
    <div class="header">
      <a href="#default" class="logo">
        Header Component
      </a>
      <div class="header-right">
        <a class="active" href="#home">
          Home
        </a>
        <a href="#contact">Contact</a>
        <a href="#about">About</a>
      </div>
    </div>
  );
}

export default Header;

```
Also add one header.css file for styling the component.

```
.header {
    overflow: hidden;
    background-color: #f1f1f1;
    padding: 20px 10px;
}

.header a {
    float: left;
    color: black;
    text-align: center;
    padding: 12px;
    text-decoration: none;
    font-size: 18px;
    line-height: 25px;
    border-radius: 4px;
}

.header a.logo {
    font-size: 25px;
    font-weight: bold;
}

.header a:hover {
    background-color: #ddd;
    color: black;
}

.header a.active {
    background-color: dodgerblue;
    color: white;
}

.header-right {
    float: right;
}

@media screen and (max-width: 500px) {
    .header a {
        float: none;
        display: block;
        text-align: left;
    }

    .header-right {
        float: none;
    }
}
```
Add Footer Component and header.css

```
import React from 'react';
import './footer.css';

function Footer() {
  return (
    <div class="footer">
      <p>Footer Component</p>
    </div>
  );
}

export default Footer;

```
add footer.css

```
.footer {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    background-color: #f1f1f1;
    color: black;
    text-align: center;
}
```
Import Header and Footer Component in App Component.

```
import React from 'react';
import ReactDOM from 'react-dom';
import Footer from './Footer';
import Header from './Header';

import './index.css';

const App = () => (
  <>
    <Header />
    <Footer />
  </>
);
ReactDOM.render(<App />, document.getElementById('app'));

```
Our app will look like this after adding Header and Footer.


![app-preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/csru7jakvv5qx58p31xv.png)

## Exposing Components to remotes
Now lets expose these two components so that we can use it in Shell app.

Open webpack.config.js of common-components-lib and update code inside plugin like this:

```
new ModuleFederationPlugin({
      name: 'common_components_lib',
      filename: 'remoteEntry.js',
      remotes: {},
      exposes: {
        './Header': './src/Header.jsx',
        './Footer': './src/Footer.jsx',
      },
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        'react-dom': {
          singleton: true,
          requiredVersion: deps['react-dom'],
        },
      },
    }),
```
Note: We updated only "exposes".

## Consume components in Shell app.

Now open webpack.config.js of Shell app and update code inside plugin.

```
const HtmlWebPackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

const deps = require('./package.json').dependencies;
module.exports = {
  output: {
    publicPath: 'http://localhost:3000/',
  },

  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
  },

  devServer: {
    port: 3000,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /\.m?js/,
        type: 'javascript/auto',
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.(css|s[ac]ss)$/i,
        use: ['style-loader', 'css-loader', 'postcss-loader'],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: 'shell',
      filename: 'remoteEntry.js',
      remotes: {
        common_components_lib:
          'common_components_lib@http://localhost:3001/remoteEntry.js',
      },
      exposes: {},
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        'react-dom': {
          singleton: true,
          requiredVersion: deps['react-dom'],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: './src/index.html',
    }),
  ],
};

```
Note: We updated only remote.

> Make sure you use same name as the app name inside the plugin.
In our case app name is "common_components_lib" and "shell"


![webpackConfig](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnth2xzqi7x90zg0kq9z.png)


![webpackConfigShell](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lrg6plnkg313kx5buetg.png)

## Render remote(Components from micro apps) in Shell App
Now its time to test our application by actually importing remote components in Shell application.

Inside App.jsx, import our Header and Footer components from common-components-lib app.

```
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom';

const Header = React.lazy(() => import('common_components_lib/Header'));
const Footer = React.lazy(() => import('common_components_lib/Footer'));

import './index.css';

const App = () => (
  <>
    <Suspense fallback={<>Loading...</>}>
      <Header />
      <Footer />
    </Suspense>
  </>
);
ReactDOM.render(<App />, document.getElementById('app'));

```
Note: We used Lazy Loading to import the remote components. To know more about the lazy loading read the official documentation from [here](https://reactjs.org/docs/code-splitting.html#reactlazy).

## Time to run the Shell App.

Restart both the application, as we made changes in webpack.config.js.

Once both apps restarted check if Header and Footer is visible on Shell app.

Yeah!!😍

![final](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iik7ds4zv9213oz3zevt.png)

## Conclusion
This article is focused on the setup of the micro frontend application and we successfully configured it.

> Please do share your feedback and experiences with Micro Frontend in the comments section below. I’d love to see what you come up with!

If you found this article useful, please share it with your friends and colleagues!❤️

Read more articles on Dev.To ➡️ [Shivam Pawar](https://dev.to/shivampawar)

Follow me on ⤵️
🌐 [LinkedIn](https://www.linkedin.com/in/shivam-prakash-pawar/)
🌐 [Github](https://github.com/shivam-pawar)