Harsh Patel 🕸 Web aficionado 💻 Writer + Programmer 🎯 Dreams ➡️ Vision ➡️ Reality

Build a micro-frontend application with React

7 min read 2031

Create Micro Frontend App React

Editor’s note: This article was last updated 28 February 2023 to reflect changes to the code. 

Working on large-scale projects and managing their codebases can be a big challenge for teams. Although micro-frontends have been in the picture for a while, they are growing in popularity because of their unique features.

With a micro-frontend, multiple teams can work on individual modules of the same project without impacting the other modules; it doesn’t matter how many modules are added to a current system.

In this article, we’ll cover the basics of what a micro-frontend is and learn how to implement one using React. We’ll also discuss the advantages of using micro-frontends in your applications. Let’s get started!

Jump ahead:

Introduction to micro-frontends

The current web development trend involves building a frontend monolithic app that sits on top of a microservice architecture. But, as developers on different teams contribute to this frontend monolith, it becomes increasingly difficult to maintain. Micro-services provide a solution for this.

The term micro-frontend extends the concept of microservices to the frontend; a micro-frontend is to the frontend what microservices are to the backend. Essentially, the goal of a micro-frontend is to treat a web app as a composition of features owned by different, independent teams with different missions; each team works end-to-end, from databases to the UI.

Micro-frontends don’t follow any particular structure and have no fixed boundaries. Your project will likely evolve as time passes, and you may need to revise your micro-frontend as you go along:

Micro Frontend Structure Diagram

Image source: https://microfrontends.com/

React is a popular frontend tech stack, so it’s a great choice for implementing a micro-frontend. The micro-frontend architecture is still fairly new and is still being adopted by different frameworks, so best practices are still evolving. Therefore, you may find it challenging to implement a micro-frontend from scratch. Here, the create-mf-app package comes in.

According to its docs, create-mf-app creates either a module federation application, API server, or library based on one of its templates. It is framework agnostic, meaning it supports multiple frameworks and libraries including Preact, React, Svelte, etc.

Best practices for micro-frontends

Let’s cover some best practices for you to keep in mind when implementing a micro-frontend architecture.

Isolate team code

Each team should develop its features as an independent app, without using a shared state or depending on global variables. Consequently, there should be no sharing of runtime, even if all teams use the same framework.

Establish team prefixes

When isolation is not yet possible, teams should agree on the ownership of namespaces to avoid possible collisions, i.e., CSS, events, local storage, etc.

Build a resilient web app

Each independent team should implement resilient features; even if JavaScript is not enabled or it fails, the feature should still work. Additionally, you should foster performance through universal rendering and progressive enhancement.



Use native browser API over custom APIs

You should favor browser events for communication instead of building a global pub/sub system; keep cross-team APIs simple.

Advantages of using a micro-frontend

Simply put, micro-frontends make web applications more maintainable. If you’ve ever been part of building a large application, you know it’s very tedious to manage everything; micro-frontends work similarly to the divide and conquer rule. Now, let’s understand the most valuable benefits of using a micro-frontend.

Deployment and security

A significant advantage of the micro-frontend architecture is that you can separate a single body into individual pieces that can be deployed independently. Vercel can support an individual repo with different frontends regardless of the language or framework, deploying them together. Otherwise, you can use deployment services like Netlify. Once the micro-frontend is deployed, you can use it as an individual frontend only.

To secure your micro-frontend, you can use an SSL certificate like Wildcard, a single or multi-domain, or a SAN SSL certificate. One SAN or multi-domain SSL certificate can secure multiple sites and subdomains.

Technology agnosticism and scalability

With a micro-frontend architecture, you can combine any language or framework in a single project, like React, Vue, Angular, etc. Each frontend team can independently choose and upgrade its own tech stack without an obligation to coordinate with other teams.

Faster development

Your team can develop and deploy your frontend whenever you want. There are zero dependencies associated with individual modules, meaning releases can be done quickly. The main goal of defining the micro-frontend is faster iterations.

Easier learning curve

Each team handles an isolated app feature, which is easier for new developers to understand compared to a frontend monolith. Consequently, the learning curve is linear, translating to lower input costs and higher overall output for new developers.

Vertical domain ownership

Before the introduction of micro-frontends, vertical domain ownership was only possible on the backend via the microservices architecture. Companies could scale product development among independent teams to promote ownership of the backend, however, the frontend remained monolithic.

With the introduction of the micro-frontend, the frontend is split into components with vertical domains owned by each team, ranging from the database to the UI.

Code reusability

Micro-frontends foster code reusability since one team can implement and deploy a component that can be reused by multiple teams.

Easy testing

Before jumping into integration testing, it’s better to test individual pieces of an application. Teams will test the micro-frontend before testing the application, thereby decreasing the chances of bugs in the real system.

Apart from that, other advantages include a small codebase that’s easily maintainable and the ability to quickly add or remove any module from the system.

Prerequisites

In this tutorial, we’ll build a micro-frontend with React. To follow along, you’ll need the following:

To follow along with the code, you can check out the GitHub repo for this project.

Bootstrapping micro-frontends

Create an application folder called micro-frontend-react. To bootstrap a React micro-frontend app, from this folder, run npx create-mf-app and pass the following data to the interactive terminal:

  • Name: home
  • Project type: Application
  • Port number: 3000

Select React, JavaScript, and Tailwind as your stack. A React micro-frontend application called home will be bootstrapped for you. In your terminal, you should see the following:

Bootstrap Micro Frontend React

To test the app from the home folder, run yarn install to install all dependencies. Then, run yarn start to start the dev-server. If everything was successful, you should see the following on your screen:

React JavaScript Tailwind Project Structure

From the about folder, repeat the steps from above using the following data:

  • Name: about
  • Project type: Application
  • Port number: 3001

Like before, select React, JavaScript, and Tailwind as your stack, and the application will be bootstrapped for you.

Finally, to test the app, install the required dependencies by running yarn install. Then, start the dev-server by running yarn start. If everything was successful, you should see the following on your screen:

Test Micro Frontend App Dependencies

Implementing a micro-frontend

In our micro-frontend implementation, the home application will contain and expose two components, Header and Footer. The about application imports and consumes these components.

To implement this, in the src directory in the home application, create two components, Header.jsx and Footer.jsx. Add the following respective code snippets to Header.jsx and Footer.jsx:

import React from "react"
export default function Header() {
    return (
        <div className="p-5 bg-blue-500 text-white -text-3xl font-bold">
            Micro Frontend Header
        </div>
    )
}
import React from "react"
export default function Footer() {
    return (
        <div className="p-5 bg-blue-500 text-white -text-3xl font-bold">
            Micro Frontend Footer
        </div>
    )
}

Next, update the App.jsx component to use the following navbars:

import React from "react";
import ReactDOM from "react-dom";
import "./index.scss";
import Header from "./Header"
import Footer from "./Footer";

const App = () => (
  <div className="text-3xl mx-auto max-w-6xl">
    <Header />
    <div className="my-10">
      Home page Content
    </div>
    <Footer />
  </div>
);

ReactDOM.render(<App />, document.getElementById("app"));

Test the app by restarting the server, and you’ll get the following:

Update App JSX Component Use Navbar

We need to build the about page in the about app. To do so, update the App.jsx component in the about app, as shown below:

import React from "react";
import ReactDOM from "react-dom";
import "./index.scss";
const App = () => (
  <div className="text-3xl mx-auto max-w-6xl">
    <div class="text-center">
      <img
        src="https://mdbcdn.b-cdn.net/img/new/avatars/8.webp"
        class="rounded-full w-32 mb-4 mx-auto"
        alt="Avatar"
      />
      <h5 class="text-xl font-medium leading-tight mb-2">John Doe</h5>
      <p class="text-gray-500">Web designer</p>
    </div>
  </div>
);

ReactDOM.render(<App />, document.getElementById("app"));

Restart the dev-server, and you’ll get the following:

Restart App About Page

From the UI above, we see the need for header and footer navigation. But, we don’t need to create duplicate copies since we can share them via micro-frontends.

Adding module federation

We noted above that the about page in the about app needs to consume the Header and Footer components of the home application. To do this, we need to add module federation.

We’ll begin by turning the Header and Footer components of the home application into micro-frontends so that components in other applications can consume them.

Open the webpack.config.js file in the home app, which is already created and configured by the create-mf-app package. First, update the exposes property in the ModuleFederationPlugin configuration, as seen below:

exposes: {
        "./Header": "./src/Header.jsx",
        "./Footer": "./src/Footer.jsx"
      },

In the code above, we specified that the home application exposes the Header and Footer components as micro-frontends. Consequently, these components can be shared.

Now, restart the server. Although nothing changes in the UI, a remote entry file has been created for us under the hood. To view the remote entry file, navigate your browser to the URL localhost:3000/remoteEntry.js, and you’ll see the following:

React Micro Service Entry File

This remote entry file, remoteEntry.js, is a manifest file of all the modules that are exposed by the home application.

To complete our setup, copy the link of the manifest file, localhost:3000/remoteEntry.js, then update the remotes property of the ModuleFederationPlugin configuration in the webpack.config.js file in the about app, as seen below:

remotes: {
        home: "[email protected]://localhost:3000/remoteEntry.js",
      },

The code above specifies that the about component has a remote micro-frontend application called home that shares its module with it. With this setup, we can access any of the components exposed from the home application.

Now, update the App.jsx component of the about application with the shared navbars, as seen below:

import React from "react";
import ReactDOM from "react-dom";
import "./index.scss";
import Header from "home/Header";
import Footer from "home/Footer";
const App = () => (
  <div className="text-3xl mx-auto max-w-6xl">
    <Header />
    <div class="text-center">
      <img
        src="https://mdbcdn.b-cdn.net/img/new/avatars/8.webp"
        class="rounded-full w-32 mb-4 mx-auto"
        alt="Avatar"
      />
      <h5 class="text-xl font-medium leading-tight mb-2">John Doe</h5>
      <p class="text-gray-500">Web designer</p>
    </div>
    <Footer />
  </div>
);
ReactDOM.render(<App />, document.getElementById("app"));

Restart the dev-server, and you’ll see following in your browser:

Restart Dev Server Browser Output

From the code above and the displayed UI, we see that we have successfully shared components between two applications using micro-frontends.

Conclusion

In this article, we explored the concept of micro-frontends with examples, discussing their advantages over frontend monolithic applications and other available setups. Micro-frontends offer some great features and are easy to adopt.

With create-mf-app, we implemented the micro-frontend architecture as easily as using Create React App. Personally, I like the micro-frontend style because it’s easily maintained among teams. Additionally, frontend building and security are managed pretty elegantly.

I hope you enjoyed this article, and be sure to leave a comment if you have any questions. Happy coding!

Revisions to this article were made by Lawrence Eagles

LogRocket: Full visibility into your production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket combines session replay, product analytics, and error tracking – empowering software teams to create the ideal web and mobile product experience. What does that mean for you?

Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay problems as if they happened in your own browser to quickly understand what went wrong.

No more noisy alerting. Smart error tracking lets you triage and categorize issues, then learns from this. Get notified of impactful user issues, not false positives. Less alerts, way more useful signal.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Harsh Patel 🕸 Web aficionado 💻 Writer + Programmer 🎯 Dreams ➡️ Vision ➡️ Reality

39 Replies to “Build a micro-frontend application with React”

  1. Funny that all MFE tutorials out there are in Javascript. Is MFE with Typescript a myth?

  2. Hi,Does the above solution of using webpack5 module federation plugin also support server side rendering in nextjs.

  3. Hi, do you have a repo with the code? I tried to replicated and lot of errors appeared in different steps.

  4. Hi,
    I did one-to-one what in your tutorial, but I have the error while importing the header component from the fe1 in the fe3 app

    ReferenceError: fe1 is not defined
    while loading “./header” from webpack/container/reference/fe1

  5. I am unable to get this to work. Can you post a repo of the source? Same error as Pawel. while loading “./header” from webpack/container/reference/fe1

      1. Hey, did you have the time to put this code on a github? I am really needing it to work, BUT, i just cant expose the remoteEntry.js file. Can you help me?

              1. Left issues and PR, code would never work if fe2 is called app1.

                Can you please upload the working code of the post and some more detailed steps to reproduce the working solution?

                Blog post instructions didn’t produce a working project as all the reader comments suggest. Code on GitHub doesn’t work either, so a working code and a list of tested reproducible step would help.

                1. I have updated README.MD file and listed few more steps. Also, posted video for the reference. Code is working as per the function.

  6. Hi Harsh Patel,
    Thank you for the step by step tutorial. But unfortunately facing the same issue as Chris and Pawel. while loading “./header” from webpack/container/reference/fe1.
    Could you please upload your code to github?

  7. I’ve read somewhere you would need this plugin @module-federation/nextjs-mf to make things work. Can you relate to this?

  8. Hi Harsh,
    Thanks for taking the time to create this tutorial. It seems that your repo is out of sync with your post though; It would be super helpful for your readers if you updated the post and also added a little more instruction around how to run the micro frontends in development.
    Thanks!

  9. I’m not really sure how you managed to get this to work. I followed your tutorial like many others but was unsuccessful. One thing I came across was the nextjs-mf plugin. On their github page they say that “Module Federation in Next.js depends on @module-federation/nextjs-mf It will not work unless you have access to this plugin, which is not free.” You can see the page here: https://github.com/module-federation/module-federation-examples/tree/master/nextjs. Probably important for anyone trying to follow this tutorial.

    1. For anyone interested, I managed to get a next based mfe setup working and you can see the source here: https://github.com/ChristopherHButler/nextjs-mfe-poc/tree/master/container
      It does not support server side rendering because the nextjs-mf plugin is currently not free (they are working to make it free and would appreciate sponsorship! – I am not affiliated with them in any way, just think it is a worthy project). Check the readme for a few extra notes on the repo. Hope this helps someone.

      1. Hey Christoper How did you manage to create remoteEntry.js file for the next app for me build command run completely fine but I cannot see any remoteEntry.js file

      2. Hi Christopher, I cloned your repo and am glad to say everything works as stated on the README. However, I would like to expose a NextJS remote entry to another NextJs consumer app. I’ve been able to create the remoteEntry.js file with the build command but I’ve not been able to access the file on the browser and on the consumer app.

    2. I have achieved it using Webpack 5 module-federation. I need to check @module-federation/nextjs-mf plugin. If It works with that plugin I’ll update my code based on it. I’ll definitely explore that package soon and see if there’s any workaround for free or need to use paid only. Also, need to check for Next.JS version compatibility.

    1. Hey, it’s not necessary to add it in _document.js as you are already setting it up in next.config.js. I have added it to just check whether it works that way or not. Definitely we can omit it.

  10. Tried w/ github code but lots of errors. The readme should be more explicit if this should in fact work

Leave a Reply