Micro Frontends in React: A Practical Guide

Use micro frontends for building complex modern applications in a scalable way

Fernando Doglio
JavaScript in Plain English
13 min readMar 27, 2023

--

Image by LeonardoAI

In the fast-paced world of modern web development, building complex applications that can scale effectively has become a top priority.

To achieve this, developers have turned to micro frontends, an approach that allows for the creation of smaller, independent user interfaces that can be combined to form a cohesive whole.

In this practical guide, I’ll show you how you can implement micro frontends in React using Bit reusable components.

Whether you’re a seasoned developer looking to optimize your app’s performance or a newcomer to the world of micro frontends, this guide will provide you with the tools and knowledge you need to build modern, scalable applications with ease.

So let’s get cracking!

Using Bit to build micro frontends

I’m going to assume you already know what a micro frontend is, or at least you understand enough to follow along.

If you’ve never heard about micro frontends before, I encourage you to read about them and then get back there to understand how to implement your own.

For this tutorial, I’m going to be using Bit, mainly because their concept of composable components lends very well to using them as micro frontends.

So if you don’t have Bit installed yet, either use the following line to install it or follow the steps from their documentation:

npx @teambit/bvm install

Either way, once installed, the next thing you’ll want to do is go to their website and sign up. It’s totally free and you’ll then be able to create your own “scope”, which is where you’ll group your micro frontends.

So once inside, click on the “New” button on the top right corner, and then select “Scope”.

You should see something like this. Make sure to choose the “Personal” option (unless you’re already looking to share this with your team), and then enter a name. I’ve gone with “microfrontend” but you can choose whatever you want.

You should see something like this after clicking on “Create”:

We’re all set for now, let’s take a look at what we’re going to build.

Building a website with micro frontends

For this tutorial I’m going to show you how you can build a working website using React and two different micro frontends:

  • A blog: This micro frontend will show a list of articles.
  • A documentation site: This micro frontend will simulate a documentation site with a few internal links.

We’ll be integrating both micro frontends as composable components with Bit, and then we’ll install them into a host application that will help you navigate between them.

All of this using nothing extra but React and Bit.

This is what the final result will look like:

You can see that when I click on “Blog” 3 posts appear, and when I hit “Documentation”, a new sub-menu appears and different sections are browsable.

This looks like a single application, but in fact, it isn’t.

Let’s look at the overall process first.

The build plan

Here’s the deal, we’re going to be building:

  1. The blog, which is going to be a very simple SPA showing pre-defined content on a single page. We’re going to encapsulate the whole thing inside a React component and we’re going to export this component to Bit.cloud.
  2. The documentation site, which will have several routes and other files to show that you can have a complex site inside a composable component. We’ll then turn it into a React component and export it into Bit.cloud.
  3. Finally, we’ll build a brand new React app that will import the previous two components and through a simple navigation menu, it’ll show one or the other.

And thus, we’ll have a seemingly unique app that is actually composed of two independent micro frontends.

💡 Consider watching this video before you begin:

So let’s start with the blog.

Did you like what you read? Consider subscribing to my FREE newsletter where I share my 2 decades’ worth of wisdom in the IT industry with everyone. Join “The Rambling of an old developer”!

1. Building our blog

I won’t be paying a lot of attention to details or UI here. I want to show you how you can build a micro frontend very fast.

So the first thing you’ll do is:

npx create-react-app my-blog

This will create a new React app inside the my-blog folder.

Now enter it and type:

bit init
bit create react blog --scope=<your-bit-username>.microfrontend

Those two lines will initiate your Bit workspace and then it’ll create a folder called microfrontend/blog at the root of your project.

Now go in there and locate the blog.tsx file and then copy the following inside it:

import React from 'react';

const posts = [
{ title: 'Post 1', content: 'This is the first post.' },
{ title: 'Post 2', content: 'This is the second post.' },
{ title: 'Post 3', content: 'This is the third post.' }
];

export function Blog() {
return (
<div>
{posts.map(post => (
<div key={post.title}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</div>
))}
</div>
);
}

That’s it, now you have your first Bit component coded. It’s completely useless, but it’ll do to explain the concept here.

Now you can go to the App.js file of your newly created React app, and paste the following code:

import React from 'react';
import {Blog} from '@deleteman/microfrontends.blog'

function App() {
return (
<div>
<h1>My Blog</h1>
<Blog />
</div>
);
}

export default App;

Notice how I’m not directly importing the component from the folder I created, but rather, I’m taking it from node_modules. That’s because Bit created a Symlink when I use the bit create command. That way my code doesn’t have to change between now and when I finally export the component.

If you run this app, you should see something like this:

So we can say that our blog is an independent application. That’s great.

Now let’s share the Bit component. We have to tag it (i.e commit the code), and export it (which will also publish it to NPM).

bit tag # this will auto-tag any changed component and it'll assign a version as well
bit export # this will export the component to Bit.cloud

With those two lines, you’ll have published your first micro frontend into Bit.cloud.

Let’s take a look at the documentation site now.

2. Building the docs

This one starts out the same way:

npx create-react-app my-docs
bit init
bit create react docs --scope=<your-bit-username>.microfrontend

Now go to the microfrontend/docs folder, and let’s copy the following code inside the docs.tsx file:

import React, { useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route, useInRouterContext, Outlet } from 'react-router-dom';

import { Nav } from './nav';

import Home from './Home';
import GettingStarted from './GettingStarted';
import APIReference from './APIReference';
import './docs.module.css'


type RouteUpdater = ([]) => null

export function Documentation({routeUpdater = null}: {routeUpdater?: RouteUpdater|null}) {

const insideRouter = useInRouterContext()
let location = window.location
let prefix = ""

if(insideRouter) {
let pathParts = location.pathname.split("/")
prefix = "/" + pathParts[1]
}



const defaultRoutes = [
{
path: prefix + "/getting-started",
element: <GettingStarted />
},
{
path: prefix + "/api-reference",
element: <APIReference />
},
{
path: prefix + "/home",
element: <Home />
}
]



useEffect(() => {
if(routeUpdater) {
routeUpdater(defaultRoutes)
}
}, [])

if(insideRouter) {
return (
<div>
<Nav/>
<Outlet />
</div>
)
}
return (
<Router>
<Routes>
{
defaultRoutes.map( r => {
return (<Route path={r.path} element={r.element} />)
})
}
</Routes>
<Outlet />
</Router>
);
}

Now, the component is not that complex, but there are a few things we need to keep in mind:

  1. This is a micro frontend, which means it has to work on its own, but it also has to work when imported into another project. This creates a problem because I’m using react-router-dom to handle the routing and you can’t define a router here, and then have the component embedded into another router. So you can see that I’m using the useInRouterContext hook to determine whether or not we’re using this component inside another router. If it’s not inside another router, then it’s running as a standalone application. Otherwise, it’s inside another app and we have to avoid defining a new Router element.
  2. Because it might be imported into another router, we have a routeUpdater function that is received via props. This function will be called when the component renders. That updater should grab the extra routes added by this component and append them to the existing ones on the host application (we’ll see that in a minute).
  3. To keep navigation clean, whenever the component is added to another application, we’ll use a prefix for the URLs defined by the component. That way everything is grouped together and we don’t run into any collision problems.

The files Home.jsx , APIReference.jsx and GettingStarted.jsx have static content in them, nothing really special.

The App.js file for this application looks like this:

import React from 'react';
import {Docs as Documentation} from '@deleteman/microfrontends.docs/dist'

function App() {
return (
<div>
<h1>My Documentation Site</h1>
<Documentation />
</div>
);
}

export default App;

Again, you can see the import statement for our reusable component. It’s ready to be exported. Right now, as a standalone app, it looks like this:

We can now tag and export our component, like this:

bit tag
bit export

And once that is done, you can visit your Bit scope online, in my case that would be https://bit.cloud/deleteman/microfrontends and you can see your two components published:

Building a website using your new micro frontends

With everything we’ve done so far, we can create a min “host” website that will import both components and use them.

That way we can create a single experience out of multiple independent ones.

To do that, we’ll start like we always do:

npx create-react-app my-site
cd my-site
bit init

With those three lines, we can now install our components. To do that, we can either use Bit or any of the other options.

If you click on one of the components and then on the “Use” button on the top right section of the screen, you’ll see all the options you have when it comes to installing these components:

I’m going to do it with NPM, so first I have to configure Bit’s registry, like this:

npm config set '@deleteman:registry' https://node.bit.cloud

That line makes it so that anytime I try to install a package from “@deleteman”, it’ll get them from Bit’s NPM registry (instead of using the default one).

Now I can simply do:

npm i @deleteman/microfrontends.blog
npm i @deleteman/microfrontends.docs

And with that, I have my two micro frontends (slash reusable components) installed. Now I can go to the newly created App.js file and put this code there:

import { Documentation } from "@deleteman/microfrontends.docs/dist/docs"
import { Blog } from "@deleteman/microfrontends.blog/dist/blog"

import React, { useState } from "react"
import { Routes, Route, Link, Outlet } from "react-router-dom"


export default function App() {

function updateRoutes(routes) {
setRoutes([...defaultRoutes, ...routes])
}


const defaultRoutes = [
{
path: "/blog",
element: <Blog />
},
{
path: "/docs",
element: <Documentation routeUpdater={updateRoutes }/>
}
]


const [routes, setRoutes] = useState(defaultRoutes)

return (<div>
<nav>
<ul>
<li>
<Link to="/docs">Documentation</Link>
</li>
<li>
<Link to="/blog">Blog</Link>
</li>
</ul>
</nav>
<Routes>
{
routes.map( r => {
return (<Route path={r.path} element={r.element} />)
})
}
</Routes>
</div>

)
}

Now, here is when the routeUpdater function from the documentation component comes into play.

Notice how I’m setting up the routes using a state variable with a list of potential routes. When I render the Documentation component, I’m passing the function updateRoutes which simply calls the setRoutes function.

But by doing so, I ensure that when we render the documentation sub-site, the routes are updated to take into account the routes provided by that component. If I don’t do that, then whenever we click on a link inside the Documentation site, we’ll get a 404 error.

Finally, keep in mind this is the App.js file, so the index.js needs to define the actual router and wrap the App component around it. Like this:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter as Router, Outlet} from 'react-router-dom';


ReactDOM.render(
<React.StrictMode>
<Router>
<App />
<Outlet />
</Router>
</React.StrictMode>,
document.getElementById('root')
);

With that, once you start this application, you’ll see the full site with both sections operational.

Why go through all this trouble?

We had to create two different components, version them and publish them to finally be able to build the website we were looking for.

Isn’t that too much hustle? Why go through all this trouble?!

Actually, no, it’s not!

The examples I showed you here are oversimplified. I built a “blog” using a single file and a “documentation site” using a couple more. But in reality, each of those is a full project on its own and they might take quite some time to get “right”.

Let alone create the whole thing while building it all into a single, unified, web application.

That’s where micro frontends start making sense.

One of the main advantages of using micro frontends is the ability to break down complex applications into smaller, more manageable parts (like our mega site into an individual blog and a documentation site).

This approach allows for independent development and deployment of individual features, reducing the risk of errors and conflicts that can arise when multiple developers work on a single, monolithic codebase.

Micro frontends also offer greater flexibility and agility in terms of scaling and updating an application. With micro frontends, teams can work on specific components without having to worry about the impact on other parts of the application, enabling faster development cycles and more rapid deployment of updates.

Another key benefit of micro frontends is the potential for better performance and user experience. By breaking an application down into smaller, more focused pieces, developers can optimize each component for its specific functionality, resulting in faster load times and a smoother user experience overall.

On top of that, the reusability factor is crazy, especially if you factor in other tools like Bit that supercharge your micro frontends. Thanks to this combination, reusing your micro frontends is as simple as looking for the right one on Bit.cloud and npm install it (or bit install it). And the cherry on top, collaborating with other teams on the same components is very easy through Bit.

If you want to know more about how to collaborate with Bit on multiple components. Check out this guide.

Overall, micro frontends offer a powerful solution for building complex applications that can scale effectively and adapt to changing requirements over time. With their focus on modularity, flexibility, and performance, they are quickly becoming a go-to approach for modern web development.

Learn how to speed up your web development process with micro frontends:

When it comes to creating a big and complex application, it’s always a good idea to think of ways in which you can split it up. The good ol’ divide and conquer methodology is quite effective in these scenarios.

We’re used to doing that for the backend, but micro frontends and tools like Bit now allow us to do it on the frontend just as easily. Building React applications, encapsulating them into a reusable component and then composing an even bigger one out of several of these components is not only a great idea but relatively easy to do.

Find out more about reusing React components:

Hopefully, after reading this practical guide you’ll be ready to tackle your next project in a more scalable way!

Build frontend apps with independent components and teams using Micro Frontends

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--

I write about technology, freelancing and more. Check out my FREE newsletter if you’re into Software Development: https://fernandodoglio.substack.com/