Building Frontend Platforms: Micro-frontends and Monorepo

Meiyappan Kannappa
7 min readJun 15, 2024

--

When we talk about software platforms, often it is always about the server-side / back-end capabilities built on Java, Python or nodejs. However, most of the time FrontEnd apps are cursed as it is developed in silos as big monoliths. Perhaps there is always a thought process that Frontend is used to create a consumer experience on top of the Software Platform.

Let us take a fictional example of a Home Food ordering application named Visa Foods from my previous article Software Platform and its Business Value, where software platforms consist of backend capabilities composed to provide online menu search, ordering and tracking. The website is to get the experience of Monolith as depicted in diagram below

Each of the capabilities is built as a microservice by the individual team and the irony is the frontend application providing the experience is developed by a single team.

This works perfectly fine, but how about if Visalakshi looks to extend her business to multiple cities expecting at least 100 users minimum in the system for a minute at any time. Expand her business from just home food ordering to restaurant orders, include reviews & ratings and provide a unique experience for consumers looking to order home foods and restaurants.

Last but not least, since its B2C website it should always be up and running 24x7.

Now Visa Foods have two options 1) continue using monolith scaling the app as needed 2) Break the monolith in to micro frontends

Though option 1 is feasible, it is sub-optimal solution and cannot meet the growing business expansion, sudden surge in users for search of online food increase may cause slowness in the entire application and can impact core webvitals score of the overall application as well. Further adding to complexity if Visa foods need to bring in new experiences it will be constrained by the Monolith Frontend.

I will go deep in to the Option 2 now,

What is Micro-Frontend?

Microfrontend (MFE) is an architectural style for building web applications. It essentially breaks down a large frontend application into smaller, independent and self-contained modules. These modules, called micro frontends, can be developed, deployed, and updated independently by different teams.

Microfrontends are not something new and have existed for years now, have you heard of iframe, where you embed a web application into another web application using <iframe> tag. Though its not recommended it can be still considered to be Micro-frontend. Large enterprises have multiple web application composed to provide consumer experience. e.g Amazon

Microfrontends are inspired by Microservices architecture used in backend development. The term Micro Frontends first came up in ThoughtWorks Technology Radar at the end of 2016. It offers a way to build complex web applications with improved maintainability, scalability, and developer experience.

Each of the microfrontends will be developed and deployed by individual product teams with their choice of tech stack be it reactjs, nextjs, vue or htmx, and their release cycle is independent without single point of failure on the web. Each microfrontends can be scaled based on the needs and the traffic.

Now when we apply the microfrontend concept to Visa Foods it will be like the below

How to build Microfrontends ?

When you surf through the internet you can find many ways to build micro-frontends. However, all this boils down to two major approaches

  1. Run time composition
  2. Build time composition

P.S Various MFE patterns like Server side integration, edge site compositions are not listed here.

Run Time composition

Each website capability will developed as individual application and will be composed in the runtime to provide web experience to the consumer.

There are many ways to achieve this, as said even iFrame will be in this category.

Trending today when we say Microfrontend is Module Federation. This would have a shell application that will act as a host application and will pull the website components from other microfrontends during runtime to provide the website experience. Very similar to how Microservices interact with each other using APIs, the host application will consume the exposed component as .js file through HTTP and the remote application will expose the component as .js file.

Exposing and consuming the remote components as .js file is called Module Federation.

Key takeaways for Runtime Composition

Module federation promotes lazy loading, the components from MFEs will be loaded only as needed. And a component update will not need deployment of the whole application. However, the shell app may create a single point of failure. Also, the toolsets for module federation like webpack support only Client Side Rendering, which would deem module federation unfit for SSR apps. Popular frameworks like Nextjs don't support module federation out of the box as of writing this article.

While the number of components increases it would add more complexity to the overall application, from performance, debugging & testing perspectives.

Build Time Composition ( opt. reverse proxy)

As the name suggests the microfrontend will be composed of components in the form of packages developed by various teams (like npm packages) during build time. Technically each of the microfrontend will act like a shell, thus there is no single point of failure.

Each Frontend team will develop reusable components as packages and publish it, which can be consumed by other teams and assemble the components as web pages.

During runtime, all the microfrontend applications together provide the consumer experience either with direct linking of web applications or with the option of using a reverse proxy or global load balancer route the requests to the respective microfrontend for a web page based on the route path (often called as Server side composition). The architecture would look like the one below

Key takeaways for Build time composition

Compared to Run time composition, there is no single point of failure via shell app, in this approach all the MFEs are shell apps assembling the components. This approach can be used for both Client Side Rendering and Server Side Rendering apps. Perhaps this will be well suited for apps that need better SEO indexing and improve the overall page load time. Friendly for CDN caching as well.

Technology Agnosticism will be constrained across teams, and change in the component package requires the affected MFE to rebuild and deploy. Dependency Management becomes complex as the number of components increases.

Managing the code

We have seen two different approaches to building MFEs, but how would we manage the code developed by the individual teams, and to share the component packages across teams

Polyrepo Approach

Each MFE and publishable component will have its own repositories. And will have CI/CD pipelines integrated to deploy apps and publish components to the package manager. With Polyrepo each package and component will maintain their own versions.
The performance of polyrepo will be good for each of the teams using it. Managing the standards and quality of the code across multi repo of MFE applications becomes more challenging.

Pros:

  • Modular & Independent: Each project has its own codebase, simplifying maintenance and allowing different tech stacks per project.
  • Flexible & Scalable: Teams can tailor tools and easily add/remove projects without affecting the whole codebase.

Cons:

  • Complex Dependencies: Managing dependencies across multiple repositories requires additional tools and effort.
  • Duplication & Coordination: Shared code needs duplication or separate maintenance, and coordinating changes across projects can be challenging.

Monorepo

A monorepo is not a monolith. It’s a software development strategy in which a company’s or large micro applications entire codebase is stored in a single repository. There are many trade-offs when deciding to use to Monorepo.

Monorepo can organize various applications and its dependencies in a single repo, and applications in monorepo can reuse the components, libraries, and configuration. Monorepos support an organizational culture of collaboration and support. When code is shared inside a monorepo, it means the challenges different teams face are also shared, making it easier to solve them together. Maintaining coding standards and quality becomes easier in monorepo.

Pros:

  • Code Sharing and Reusability: A single codebase allows developers to easily share code across projects, reducing duplication and promoting consistency.
  • Simplified Dependency Management: All projects use the same version of dependencies, eliminating dependency conflicts and simplifying management.

Cons:

  • Increased Repository Size: A single codebase can become large and complex over time, making it harder to navigate and maintain.
  • Slower Builds: Builds can be slower for developers who only need to work on a specific project.

Final Thoughts

The choice of building your web application either as a monolith or Microfrontend depends on various factors including organisational culture, business demands & growth for the next few years. The development team structure will also have a greater influence on choosing between monolith and MFE.

--

--

Meiyappan Kannappa
Meiyappan Kannappa

Written by Meiyappan Kannappa

Technical enthusiast, daydreamer. Design of involute software architecture for digital transformation, sustainability and cost optimization.

Responses (1)