How to Develop a Micro Frontend app with React

It is common knowledge that the best method to tackle any software issue is to disassemble the problem. Whether it be by rewriting your code to create functions that are more manageable and clear, there are multiple ways to accomplish this.

It Is only logical to disassemble apps into more manageable and isolated pieces. The micro front-end approach applies the ideas behind microservices to the front-end development of websites.

This strategy entails dividing the code for the browser-based front end into multiple micro frontends by first disassembling the application features. The goal of decoupling in software development can be realized by creating codebases that are both smaller and more focused on features.

Even though the codebases are separated, the user experiences are consistent. In addition, each codebase has the capability of being independently implemented, improved, updated, and deployed.

This approach is a solution favored by miniature front-end devotees. Applications written in JavaScript are always started by a container, independent of the frameworks or versions they use.

These applications, both new and legacy, integrate without any hiccups and appear to function as one application.

Why use Micro Frontend?

Large applications have profited in multiple ways from the development of microservices, which have advanced in recent years. It is helpful in the process of efficiently developing, deploying, and scaling the separate components of the application backend.

Nevertheless, many developers have become aware that similar difficulties exist for the front-end as well. It is at this stage that the breaking up of the frontend monolith into individual micro front-ends usually begins.

A micro front-end is a section of the frontend that an individual team or multiple teams may independently create, test, and deploy as a single unit.

However, you need to make sure that you glue these elements together so seamlessly that it seems to the end consumers as though they are using a single web application.

Software Developer
Software Developer

The following is a list of the most crucial elements that you want at the end:

1. Split app development into basic, independent component codebases.

2. Give teams the autonomy to construct and deploy components as quickly as possible.

3. Integrate and exchange components across several apps in a time-efficient manner.

4. Simplify the process of collaboration, modifications, and updates.

5. Ensure design and development consistency.

All of this is accomplishable with the proper component infrastructure in place. You can construct apps and experiences together using separate components, which will allow you to address the difficult problems associated with expanding frontend development.

Method 1: How to Launch Via Module Federation

A JavaScript application can dynamically load code from another application via module federation, sharing dependencies in the process.

The Module Federation Webpack will obtain the missing dependency from the federated build origin if an application consuming a federated module lacks a dependency required by the federated code.

What you’ll need:

  • Code Editor
  • Basic experience with Webpack 5+ and React.js.
  • Ensure that you have the most recent Node installed.js

In this article, we’ll make two apps:

The first is a container app that will serve as the foundation for the smaller frontends. The counter app, which will be rendered inside the container app, comes in second.

Setting up the surroundings comes first. To construct a react app, we’re using create-mf-app.

1. Container

Use “create-mf-app” to install and bootstrap the application by running the npx command listed below. Let’s refer to our program as “container.”

npx create-mf-app

Micro Frontend with React.js and Module federation | Rahul Sharma(DevsMitra)
npx create-mf-app

Following the completion of the first phase, the directory will first appear to be something like this:

It is identical to the create-react folder structure except for index.js used to dynamically launch the app.

import(‘./App’);

2. Counter App

For the counter app we will also be using “npx create-mf-app”.

npx create-mf-app

Create a Counter component in the components folder within the counter app.
npx create-mf-app

Create a Counter component in the components folder within the counter app.

src/components/Counter.jsx

import React, { useState } from "react";
export const Counter = () => {
    const [count, setCount] = useState(0);
    const onIncrement = () => setCount(count + 1);
    const onDecrement = () => setCount(count - 1);
    return (
      <div>
        <h1>Counter App</h1>
        <p>Current count: <strong>{count}</strong></p>
        <button onClick={onIncrement}>+</button>
        <button onClick={onDecrement}>-</button>
      </div>
    );
}

Update the webpack.config.js file that’s located within the Counter app. Include the ModuleFederationPlugin in the list of plugins while using the following configuration:

webpack.config.js

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:8081/",
  },
  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },
  devServer: {
    port: 8081,
    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: [ // This is important part
    new ModuleFederationPlugin({
      name: "counter",
      filename: "remoteEntry.js",
      remotes: {},
      exposes: {
        "./Counter": "./src/components/Counter",
      },
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        "react-dom": {
          singleton: true,
          requiredVersion: deps["react-dom"],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
  ],
};

Let’s understand what each option is:

  1. name: Name of the remote app
  2. filename: Entry point(remoteEntry.js) for the counter app.
  3. remotes: Add remotes entry here (relevant for the container)
  4. exposes: All the component names that you want to expose to the container app.
  5. shared: container all the dependencies that you want to share between the container and the counter app.

Let’s update the webpack.config.js file inside the Container app.

webpack.config.js

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:8080/",
  },
  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },
  devServer: {
    port: 8080,
    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: [ // This is important part
    new ModuleFederationPlugin({
      name: "container",
      filename: "remoteEntry.js",
      remotes: {
        counter: "counter@http://localhost:8081/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",
    }),
  ],
};

The remote objects will be responsible for defining all the entry points made available by the remote apps. The format of the remote entry is as follows:

{ “app-name”: “name@<remote-host>/remoteEntry.js” }

src/App.jsx

import React from "react";
import ReactDOM from "react-dom";
import { Counter } from 'counter/Counter';
import "./index.css";
const App = () => (
  <div className="container">
    <h1>Container App</h1>
    <Counter /> // Micro frontend app
  </div>
);
ReactDOM.render(<App />, document.getElementById("app"));

Now, run the two apps.

When you give localhost:8080 a fast refresh, you should find the two links, and if you click on them, everything should work as programmed. The fact that our container and counter apps may both navigate freely without the need to couple the applications together via router files is a great bonus of using this method.

Method 2: Build-time Integration

Using this method, you will have a few child frontends, each of which will be distributed using npm as a separate package.

After that, you can merge them into a wrapper parent component by utilizing the framework of your choice. This component will ultimately serve as the front-end application that you deploy.

The fact that this choice is so uncomplicated is the primary advantage that it offers. You might have a very good idea of how to accomplish this on your own, but we’ll give a few additional specifics on how to get there below in case you need them.

The fact that each modification to a child component will necessitate the rebuilding and redeployment of the parent is one of the most significant drawbacks of using this strategy.

Additionally, because of the nature of this approach, it is quite attractive to couple the parent and the child.

Summary of Build-Time Integration

The following are the high-level steps for the integration that occurs during build time:

  • Build the child application(s)
  • Export the router file
  • Publish to npm (An easier way to get this done is to set up a CI pipeline to execute version bumping and publishing to npm automatically)
  • Enter it as a node module in the parent application
  • Integrate into the parent application router file

Conclusion

In this article, we covered the fundamentals of micro front-ends as well as the steps necessary to properly construct micro front-ends using React.js and Webpack.

Now we have a functional and operational micro frontend application. We hope that you were able to keep up and that you picked up some useful information along the road.

What do you think of micro frontends? Do you think they can help with productivity? Let us know in the comments!

.

Want to work with Anthony Figueroa?
We are hiring :)

Thanks to the creation of blockchain technology in 2008, a lot of developments have occurred since. For example, the creation […]
June 15
5 min read
One of the most important western philosophers of all time, Aristotle once said – “Man is by nature a social […]
December 7
5 min read
Month-over-month growth is a key metric for measuring the growth of your business.
June 18
5 min read
Quality assurance teams can use various tools to improve a company’s software. For example, a QA engineer may use a stress […]
October 2
5 min read
Startup leaders are always about making contingency plans for when things go wrong. Preparing for the worst is great. But […]
September 28
5 min read
Behind every mobile application, a UI framework determines how developers create the application and how well it performs. Today, UI […]
September 23
5 min read
Handling data is a big part of developing applications with Django. To do that, we use Django’s ORM, from retrieving […]
September 21
5 min read
DevOps has grown to be the top software development methodology worldwide. DevOps prioritizes the company and the customer by improving […]
September 21
5 min read