It is amazing how the software industry evolved over time. Back in the day, a software was a simple program. Some of the first software applications like The Apollo Missions Landing modules and Manchester Baby were basic stored procedures. Software was primarily used for research and mathematical purposes.
The advent of disruptive technologies like cloud computing and Big data paved the way for more intricate, convoluted web and native mobile applications. From e-commerce and video streaming apps to social media and photo editing, we had applications doing some of the most complicated data processing and storage. The traditional monolithic way now posed a number of challenges in terms of scalability, team collaboration and integration/deployment and often led to huge and messy The Ball Of Mud codebases.
To untangle this ball of software, came in a number of service-oriented architectures. The most promising of them was Microservices - breaking up an application into smaller chunks that can be developed, deployed and tested independently but worked as a single cohesive unit. Its benefits of scalability and ease of deployment by multiple teams proved as a panacea to most of the architectural problems. A few frontend architectures also came up. MVC, MVVM, Web Components to name a few. But none of them were fully able to reap the benefits of Microservices.
Micro FrontEnds: The Concepts
Micro Frontends first came up in ThoughtWorks Technology Radar where they assessed, tried and eventually adopted the technology after noticing significant benefits. It is a Microservice approach to front-end web development where independently deliverable front-end applications are composed into a greater whole.
With Microservices, Micro Frontends breaks the last monolith to create a complete Micro-Architecture design pattern for Web Applications. It is entirely composed of loosely coupled vertical slices of business functionality rather than in horizontals. We can term these verticals as ‘Micro-Apps’. This concept is not new and has appeared in Scaling with Microservices and Vertical Decomposition. It first presented the idea of every vertical being responsible for a single business domain and having its own presentation layer, persistence layer and a separate database. From the development perspective, every vertical is implemented by exactly one team and no code is shared between the different systems.
Why Micro Frontends?
A microservice architecture has a whole slew of advantages when compared to monolithic architectures.
Ease of Upgrades - Micro Frontends build strict bounded contexts in the application. Applications can be updated in a more incremental and isolated fashion without worrying about the risks of breaking up another part of the application.
Scalability - Horizontal scaling is easy for Micro Frontends. Each Micro Frontend has to be stateless for easier scalability.
Ease of deployability: Each Micro Frontend has its own CI/CD pipeline, that builds, tests and deploys it all the way to production. So it doesn’t matter if another team is working on a feature and has pushed a bug fix or if a cutover or refactoring is taking place. There should be no risks involved in pushing changes done on a Micro Frontend as long as there is only a single team that works on it.
Team Collaboration and Ownership: The Scrum Guide says that "Optimal Development Team size is small enough to remain nimble and large enough to complete significant work within a Sprint”. Micro Frontends are perfect for multiple cross functional teams that can completely own a stack (Micro Frontend) of an application from UX to Database design. In case of an E-commerce site, the Product team and Payments team can concurrently work on the app without stepping on each other’s toes.
Micro Frontend Integration Approaches
There are a multitude of ways to implement Micro Frontends. It is recommended that any approach for this should take a Runtime integration route instead of a Build Time integration as the former has to re-compile and release on every single Micro Frontend in order to release any one of the Micro Frontend’s changes.
We shall learn some of the prominent approaches of Micro Frontends by building a simple Pet Store E-Commerce site. The site has the following aspects (or Micro-Apps if you will) - Home or Search, Cart, Checkout, Product and Contact Us. We shall only be working on the Front-end aspect of the site. You can assume that each Micro-app has a microservice dedicated to it in the backend. You can view the project demo here and the code repository here. Each way of integration has a branch in the repo code which you can checkout to view.
Single Page Frontends -
The simplest way (but not the most elegant) to implement Micro Frontends is to treat each Micro Frontend as a single page.
It is one of the purest ways of doing Micro Frontends because there is no container or stitching element that binds the front ends together into an application. Each Micro Frontends is a standalone app with each dependency encapsulated in it and no coupling with the others. The flipside of this approach is that each frontend has a lot of duplication in terms of cross cutting concerns like headers, footers which adds a lot of redundancy and maintenance burden.
As we saw above, single-page Micro Frontend architecture has its share of drawbacks. To overcome these, we should opt for an architecture that has a container element that builds the context of the app, the cross cutting concerns like authentication and stitches all the Micro Frontends together to create a cohesive application.
As you can see, this approach is pretty neat and encapsulates a separate class for Micro Frontends. All other Micro Frontends extend from this. Notice how all the functionality related to Micro-App is encapsulated in the respective Micro Frontend. This makes sure that concurrent work on a Micro Frontend doesn’t mess up some other Micro Frontend.
Everything will work in a similar paradigm when it comes to Web Components and Custom Elements.
Since there should be minimum sharing of code between any Micro Frontend, styling the React components can be challenging considering the global and cascading nature of CSS. We should make sure styles are targeted on a specific Micro Frontend without them spilling over to other Micro Frontends. Inline CSS, CSS in JS libraries like Radium, and CSS Modules can be used with React.
Using React with Redux is kind of a norm in today’s frontend world. The convention is to use Redux as a single global store for the entire app for cross application communication. A Micro Frontend should be self-contained with no dependencies. Hence each Micro Frontend should have its own redux store, moving towards a multiple redux store architecture.
Other Noteworthy Integration Approaches -
Server Side Rendering - One can use a server to assemble Micro Frontend templates before dispatching it to the browser. SSI techniques can be used too.
IFrames - Each Micro Frontend can be a Iframe. They also offer a good degree of isolation in terms of styling and global variables not interfering with each other.
With Microservices, Micro Frontends promises to bring in a lot of benefits when it comes to structuring a complex application and simplifying its development, deployment and maintenance.
But there is a wonderful saying that goes “there is no one-size-fits-all approach that anyone can offer you. The hot water that softens a carrot will harden an egg”. Micro Frontend is no silver bullet for your architectural problems and comes with its own share of downsides. With more repositories, more tools, more build/deploy pipelines, more servers, more domains to maintain, Micro Frontends can increase the complexity of an app. It may render cross application communication difficult to establish. It can also lead to duplication of dependencies and increase in application size.
Your decision to implement this architecture will depend on a number of factors like the size of your organization and the complexity of your application. Whether it is a new or legacy codebase, it is advisable to apply the technique gradually over time and review its efficacy over time.