Micro-frontend Pratical guide - Part 2
Tags: javascript, react, microfrontend
Published: 2022-09-08 14:20:55

---
title: Micro-frontend Pratical guide - Part 2
published: true
description: Follow up article on micro frontend architecture guide
tags: javascript, react, microfrontend
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
---

In [previous post](https://dev.to/rv90904/micro-frontend-pratical-guide-part-1-42k8), we discussed **what is micro-frontend architecture** and **its pros and cons**. In this post, we'll go through the steps required in setting up the project - how to initialize the main container app and a sample module using React. 


We'll assume that our complex app needs some booking functionality. let's start with one module (booking-module) and a container(or master) app 


## Initialize Booking module with
`npx create-react-app booking-module`

`cd booking-module && npm start` make sure everything is working as expected.

Create a Counter component which will be exposed to main container app. 

```
// src/Counter.js
import React, { useState } from 'react'

const Counter = () => {
    const [count, setCount] = useState(0);
    const handleIncrement = () => setCount(count + 1);
    const handleDecrement = () => setCount(count - 1);
    return (
        <div className='counter'>
            <h3>This is Counter App Module</h3>
            <p><strong>{count}</strong></p>
            <div>
                <button onClick={handleIncrement} className='counter-btn'>+</button>
                <button onClick={handleDecrement} className='counter-btn'>-</button> 
            </div>
            
        </div>
    )
}
export default Counter;
```

Update your App.js 
```
import './App.css';
import Counter from './Counter';

function App() {
  return (
    <div className="App">
      <h3>This is Booking module</h3>
      <Counter/>
    </div>
  );
}

export default App;
```

Next step: Introduce webpack
`npm install webpack webpack-cli webpack-dev-server html-webpack-plugin`

Create webpack.config.js

```
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require("webpack").container.ModuleFederationPlugin;
const deps = require('./package.json').dependencies

module.exports = {
    mode: 'development',
    devServer: {
        port: 8082,
    },
    output: {
        filename: 'main.js',
      },
      module: {
        rules: [{ 
            test: /\.jsx?$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: { presets: [
                '@babel/env',
                ["@babel/preset-react", {"runtime": "automatic"}]
            ] },
         }, { 
            test: /\.css$/, 
            use: [ 'style-loader', 'css-loader' ] 
        }],
      },
    plugins: [
        new ModuleFederationPlugin({
            name: "bookingModule",
            filename: "remoteEntry.js",
            remotes: {},
            exposes: {
              "./Counter":"./src/Counter.js"
            },
            shared: {
              ...deps,
              react: {
                singleton: true,
                requiredVersion: deps.react,
              },
              "react-dom": {
                singleton: true,
                requiredVersion: deps["react-dom"],
              },
            },
          }),
        new HtmlWebpackPlugin({
            template: './public/index.html'
        })
    ]
};
```

Here `ModuleFederationPlugin` will expose your components as a separate bundle. Note - name field inside `ModuleFederationPlugin` will be used while importing components, so make sure you have a unique module name. 

We exposed Counter component like this 
```
exposes: {
    "./Counter":"./src/Counter.js"
}
```
Multiple components can also be exposed just like
```
exposes: {
    "./Counter":"./src/Counter.js",
    "./Timer":"./src/Timer.js"
},
```


Next Step - 
`npx webpack serve` - this will run your module instance on given port. 8082 in my case


![Booking module preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bk18iu2ov726tizymims.png)


Restructure your module's entry point file. 
By default, src/index.js is the entry file and it contains multiple import which creates problem while building bundle
Modify src/index.js file as follow - 
```
import('./bootstrap')
```

Create bootstrap.js file with following content -

```
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
```


## Initialize Main Container app

`npx create-react-app container`
`cd container`

Install Webpack dependencies
`npm install webpack webpack-cli webpack-dev-server html-webpack-plugin `

Create webpack.config.js file
```
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require("webpack").container.ModuleFederationPlugin;
const deps = require('./package.json').dependencies

module.exports = {
    mode: 'development',
    devServer: {
        port: 8080,
    },
    output: {
        filename: 'main.js',
      },
      module: {
        rules: [{ 
            test: /\.jsx?$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: { presets: [
                '@babel/env',
                ["@babel/preset-react", {"runtime": "automatic"}]
            ] },
         }, { 
            test: /\.css$/, 
            use: [ 'style-loader', 'css-loader' ] 
        }],
      },
      plugins: [
        new ModuleFederationPlugin({
            name: "container",
            remotes: {
               bookingModule:"bookingModule@http://localhost:8082/remoteEntry.js",
              },
            exposes: {
            },
            shared: {
              ...deps,
              react: {
                singleton: true,
                requiredVersion: deps.react,
              },
              "react-dom": {
                singleton: true,
                requiredVersion: deps["react-dom"],
              },
            },
          }),
        new HtmlWebpackPlugin({
            template: './public/index.html'
        })
    ]
}
```

We are now telling webpack to import module from this url and  multiple modules can be imported similar to how we did in booking module. 

```
remotes: {
               bookingModule:"bookingModule@http://localhost:8082/remoteEntry.js",
              },
```


Now you are ready to consume booking-module's component, but before we need to change the entry point of the project similar to how we did in booking module. 

create a bootstrap.js file with content
```
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

```

modify index.js file as below
```
import('./bootstrap')
```

Now import Counter from booking module and consume component
```
import Counter from 'bookingModule/Counter';

function App() {
  return (
    <div className="App">
      <h3>This is Container App</h3>
      <Counter/>
    </div>
  );
}

```

Output: 
![Main container app with booking module's componet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ufmgw0wdd2jjtvj1iih.png)


### Source code can be found [here](https://github.com/rameshvishnoi90904/react-microfrontend)

## Next steps - Deployment coming soon