Quick Summary:

This blog covers a complete guide on how one can implement a React Micro frontend, along with a firm understanding of the React Microservices Architecture, the benefits of such monolithic applications built using Micro frontend architecture React, the various implementations of the same, and an ideal tutorial for building a Micro frontend with React.

Table of Contents

Introduction to React Micro Frontend

Monolithic architecture, the norm in software development for decades, is being replaced by microservices as an alternate strategy. Initially, the success of monolithic designs has a long history. Consequently, several software vendors and industry leaders firmly believe in its benefits. However, as time changes, new technical advancements appear that are more advantageous than everyone seems accustomed to.

React micro frontend architecture is not a new concept but a progression of earlier architectural patterns. Disruptive innovation trends in social media, cloud computing, and the Internet of Things (IoT) are heavily influencing the platform of microservice architecture to penetrate the market quickly.

Thanks to the move to continuous deployment. Microservices, in the form of React micro frontend help businesses in the following ways:

  • Scalability of Build-Up
  • Quick Deployment
  • Technology-independence
  • No Insulation fault
  • Efficient upgrade and migration
  • High deployability and automatability
  • Reduced security threats and dependability
  • Shortened and cheaper development time
  • Appealing to engineers

Advantages of Using Micro Frontend in React

Utilizing Micro front architecture React can assist you in developing and deploying faster while improving maintainability. Following is the list of the benefits you avail by using micro frontend in React:

1. Simple Codebase

Dealing with large and complex codebases becomes challenging for developers. Here, the React microservices frontend plays a vital role as it separates your code into simpler ones. As a result, it makes the codebase more manageable, improves visibility, and provides clarity to write better code.

2. Enhance Scalability

One of the core benefits of micro front architecture is its improved scalability efficiency. As demand grows, each module in the micro font design scales autonomously. Moreover, horizontal scaling supports the program’s workload and traffic.

3. Improve Upgradation

It is time-consuming and requires lots of effort to add new functionality to an extensive, outdated, monolithic front-end application. However, with the help of the micro front in React, you can divide the app into distinct parts and add new features and functionality. Also, it enhances gradually by reducing interruption and adding new features without hampering the system’s scalability and performance.

4. Quick Deployment

Smaller parts and properly assigned modules make deployment easier and quicker. Moreover, microfront allows the individual deployment of each component. As a result, adding new features and functionality to your React application saves time and effort.

5. Team Autonomous

Micro front can divide a large workforce into smaller sub-groups, eventually boosting productivity and performance. In addition, your team can focus on the React micro frontend because of autonomy, promoting higher development cycles. Also, it indicates that each team member can take charge of specific aspects of the product, allowing them to create appliction effectively.

Also, it offers-

  • Technology-independence
  • No Insulation fault
  • Efficient migration
  • High deployability and automatability
  • Reduced security threats and dependability
  • Shortened and cheaper development time
  • Appealing to engineers

Building Micro Frontend with React [Tutorial]

Let us show you a tutorial guide on how to build the Micro frontend architecture React. Here, we will be building two applications: a host and remote, where the main application is the host and another is a sub-app that we plug into.

The host app will be our “main” app and the remote app will be a sub-app plugging into it.

First, we will be creating a basic React app using create-react-app.

1. In Your Root Directory

Copy Text
npx create-react-app host-app
 
npx create-react-app remote-app

This will create two apps for you:

1. host-app/
2. remote-app/

2. Adding Dependencies

Within each host-app/ and remote-app/ run:

npm install –save-dev webpack webpack-cli html-webpack-plugin webpack-dev-server babel-loader css-loader

This will install the webpack & dependencies that we need for webpack configuration.

NOTE:-Webpack Module Federation is available in version 5 and above of webpack.

After adding dependencies, we can host our app.

Do you wish to create a React Micro Frontend application for your users to hastily find them their solution and to scale your business?
Hire Reactjs developers from Bacancy as we are early adopters of the magnificent possibilities in the frontend. Our veteran React developers have years-long experience with industry-wide domains of small & big dimensions.

3. Hosting the App

Let us start with our webpack configuration

Create a new webpack.config.js file at the root of host-app/ & remote-app/:

Copy Text
//host-app/webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
 
module.exports = {
 entry: "./src/index",
 mode: "development",
 devServer: {
   port: 3000,
 },
 module: {
   rules: [
     {
       test: /\.(js|jsx)?$/,
       exclude: /node_modules/,
       use: [
         {
           loader: "babel-loader",
           options: {
             presets: ["@babel/preset-env", "@babel/preset-react"],
           },
         },
       ],
     },
     {
       test: /\.css$/i,
       use: ["style-loader", "css-loader"],
     },
   ],
 },
 plugins: [
   new HtmlWebpackPlugin({
     template: "./public/index.html",
     favicon: "./public/favicon.ico",
     manifest: "./public/manifest.json",
   }),
 ],
 resolve: {
   extensions: [".js", ".jsx"],
 },
 target: "web",
};
Copy Text
// remote-app/webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
 
module.exports = {
 entry: "./src/index",
 mode: "development",
 devServer: {
   static: {
     directory: path.join(__dirname, "public"),
   },
   port: 4000,
 },
 module: {
   rules: [
     {
       test: /\.(js|jsx)?$/,
       exclude: /node_modules/,
       use: [
         {
           loader: "babel-loader",
           options: {
             presets: ["@babel/preset-env", "@babel/preset-react"],
           },
         },
       ],
     },
     {
       test: /\.css$/i,
       use: ["style-loader", "css-loader"],
     },
     {
       test: /\.(gif|png|jpe?g|svg)$/,
       use: [
         {
           loader: "file-loader",
           options: {
             name: "[name].[ext]",
             outputPath: "assets/images/",
           },
         },
       ],
     },
   ],
 },
 plugins: [
   new HtmlWebpackPlugin({
     template: "./public/index.html",
     favicon: "./public/favicon.ico",
     manifest: "./public/manifest.json",
   }),
 ],
 resolve: {
   extensions: [".js", ".jsx"],
 },
 target: "web",
};

This basic webpack example is to get our js and jsx code transpiled using babel-loader and injected into an HTML template.

Change the start script in package.json to utilize our webpack config:-

Copy Text
 "scripts":{
    "start": "webpack serve"
  }
index.js(same for both apps)

First, we need the index.js as an entry to our app. Another file we are importing is bootstrap.js which renders the React app.

We need this extra layer of indirection because it will give Webpack a chance to load all of the imports it needs to render the remote app.

Otherwise, you will see an error like this:

The shared module is not available for eager consumption

Copy Text
//host-app/src/index.js
//remote-app/src/index.js
import("./bootstrap");

// Note: It is important to import bootstrap file dynamically using import() statement otherwise you will see the same error.

bootstrap.js(same for both apps)

Next, we define the bootstrap.js file for both repos that render our React application.

Copy Text
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
 
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
 < React. Strict Mode >
   < App / >
 </React.StrictMode>
);
App.js(In host App)

Now we can write our App.js file where the app’s main logic happens. Here we will load two components from remote which we will define later.

import(“Remote/App”) will dynamically fetch the Remote app’s App.js React component.

We need to use a lazy loader and also an ErrorBoundary component to create a smooth experience for users in case the fetching takes a long time or introduces errors in our host app.

Copy Text
// host-app/src/App.js
import React from "react";
import ErrorBoundary from "./ErrorBoundary";
const RemoteApp = React.lazy(() => import("Remote/App"));
const RemoteButton = React.lazy(() => import("Remote/Button"));
 
const RemoteWrapper = ({ children }) => (
 <div
   style={{
     border: "1px solid red",
     background: "white",
   }}
 >
   <ErrorBoundary>{children}</ErrorBoundary>
 </div>
);
 
export const App = () => (
 <div style={{ background: "rgba(43, 192, 219, 0.3)" }}>
   <h1>This is the Host!</h1>
   <h2>Remote App:</h2>
   <RemoteWrapper>
     <RemoteApp />
   </RemoteWrapper>
   <h2>Remote Button:</h2>
   <RemoteWrapper>
     <RemoteButton />
   </RemoteWrapper>
   <br />
   <a href="http://localhost:4000">Link to Remote App</a>
 </div>
);
export default App;

You can add the ErrorBoundary component from this repo.

You Might Also Like To Read:

Top React Static Site Generators for 2024
Add Module Federation(In host App)

We’re not ready to run the app just yet. Next, we need to add Module Federation to tell our host where to get the Remote/App and Remote/Button components.

In our webpack.config.js, we introduce the ModuleFederationPlugin:

Add the following code to the plugins.

Copy Text
// host-app/webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const { dependencies } = require("./package.json");
 
module.exports = {
 //...
 plugins: [
   new ModuleFederationPlugin({
     name: "Host",
     remotes: {
       Remote: `Remote@http://localhost:4000/moduleEntry.js`,
     },
     shared: {
       ...dependencies,
       react: {
         singleton: true,
         requiredVersion: dependencies["react"],
       },
       "react-dom": {
         singleton: true,
         requiredVersion: dependencies["react-dom"],
       },
     },
   }),
 ],
};

Important things to note:

Name:- It is used to distinguish the modules.

Remotes:- It is where we define the federated modules we want to consume in this app. You’ll notice we specify Remote as the internal name so that we can load the components using import(“Remote/“). But we also define the location where the remote’s module definition is hosted: Remote@http://localhost:4000/moduleEntry.js. This URL tells us three important things. The module’s name is Remote, it is hosted on localhost:4000, and its module definition is moduleEntry.js.

Shared:- It is how we share dependencies between modules. This is very important for React because it has a global state, meaning you should only ever run one instance of React and ReactDOM in any given app. To achieve this in our architecture, we are telling webpack to treat React and ReactDOM as singletons, so the first version loaded from any modules will be used for the entire app. As long as it satisfies the requiredVersion we define. We are also importing all of our other dependencies from package.json and including them here to minimize the number of duplicate dependencies between our modules.

Now, if we run npm start in the host app we will be able to see the output on the screen.

This means our host app is configured, but our remote app is not exposing anything yet. So we need to configure that also.

For Remote App

Let’s start with the webpack configuration file. As we have configured it host-app, we have some knowledge of Module Federation:

Add the following code to the plugins.

Copy Text
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const { dependencies } = require("./package.json");
 
new ModuleFederationPlugin({
   name: "Remote",
 
   filename: "moduleEntry.js",
   exposes: {
     "./App": "./src/App",
     "./Button": "./src/Button",
   },
   shared: {
     ...dependencies,
     react: {
       singleton: true,
       requiredVersion: dependencies["react"],
     },
     "react-dom": {
       singleton: true,
       requiredVersion: dependencies["react-dom"],
     },
   },
 }),

The important things we can note from the above code are:

  • Our webpack dev server runs at localhost:4000
  • The remote module’s name is Remote
  • The filename is moduleEntry.js
  • Combining these will allow our host-app to find the remote-app’s code at Remote@http://localhost:4000/moduleEntry.js

exposes is where we define the code we want to share in the moduleEntry.js file. Here we are exposing two files: < App / > and < Button / >.

Now We can set up those components and our Remote app so it can run independently.

Copy Text
import React from "react";
 
export const App = () => {
 return <div>Hello from the Remote App</div>;
};
export default App;

And we also want to expose a < Button / > component.

Copy Text
import React from "react";
 
export const Button = () => <button>Hello!</button>;
 
export default Button;

Now We have configured the Remote app and if you run npm start we can see a blank page with “Hello from the other side.”

Now you can put both repos in one folder and start both on single command:-

Copy Text
Microfrontend-demo/host-app
Microfrontend-demo/remote-app

Run npm init -y

One package.json file will be created. Now add the following changes in package.json:-

Copy Text
  "workspaces": {
    "packages": [
      "host",
      "remote"
    ]
  },
  "scripts": {
"start": "npm run start:host & npm run start:remote",
    "start:host": "cd ./host-app && npm start",
    "start:remote": "cd ./remote-app && npm start",
    "start:all": "yarn workspaces run start",
    "cleanup": "yarn workspaces run cleanup"
  },

This will run both repos in a single command. And you can see the output.

Conclusion

The developer doesn’t recommend creating a React micro frontend App using the create-react-app command. However, we hope you found this tutorial helpful.Typically, some crucial elements have contributed significantly to the popularity and momentum of micro frontend architecture.

Most product-based businesses use micro frontend architecture to speed up and lower the cost of development. In the coming years, monolith design might only be used to develop prototypes of new goods. At the same time, micro frontend architecture React that offers modularity and simple program scaling might be employed for mainstream development.

Meanwhile, get in touch with a React js development company that offers efficient and dynamic solutions, if you want more insightful guidance on micro frontend architecture

Frequently Asked Questions (FAQs)

The core idea behind developing micro frontends is to be technology agnostic, to isolate team code, to establish team prefixes, to favor native browser features over custom APIs, and to build a resilient site.

Some of the evident cons of micro front-end architecture are a lack of control over interfaces between modules, increased payloads, complex development processes, and cohesive UX.

New feature roll outs, performance enhancements, and code reusability are the pros of having a micro front-end architecture.

Hire React Developer to Build Your Next React Micro Front End

Get the following pros of micro frontends:

  • Incremental Upgrades
  • Simple, decoupled Codebase
  • Independent Deployment
  • Autonomous Teams

Our smart consultants will ease your processing.

Book a 30 min call

Build Your Agile Team

Hire Skilled Developer From Us

solutions@bacancy.com

Your Success Is Guaranteed !

We accelerate the release of digital product and guaranteed their success

We Use Slack, Jira & GitHub for Accurate Deployment and Effective Communication.

How Can We Help You?