Micro frontends (MF) is an architectural pattern to solve growing pains by building small frontend apps that have a clear scope, boundaries, and ownership, are independently deployed, and work along with other frontend apps to provide a seamless user experience.
There is a lot of hype and confusion about micro frontends. A lot of information available on micro frontend architecture proposes complex solutions that only work for large organizations that have a need and skillset to handle that level of complexity. This article is written for small and mid-size organizations facing growing pains. We review what micro frontends are, their use cases, the current state of tooling, and the implementation approach that would work for a small or mid-size organization.
Evolution of frontend architecture
This is a very biased and narrow view of frontend architecture evolution but good enough to understand how we got to MF apps.
- Vanilla JavaScript / jQuery: Web applications were written in web frameworks such as Php, Ruby on Rails, Django, Java Spring, and ASP.NET. The web pages were rendered on a server. The client-side interaction was done with Vanilla JS/jQuery. All of the code was in one single monolithic code base that was hard to scale and maintain.
- Single Page Apps (SPA): Frontend code increased in complexity to provide rich user experiences. SPA architecture came into existence to manage code complexity by separating concerns. SPA handles user interfaces, interactions, and navigation in browsers. Backend (BE) logic gets abstracted into APIs. FE and BE are separate monoliths.
- Universal Apps: SPA evolves into Universal Apps that run on both server and client to provide better SEO and performance. BE embraces microservices architecture. FE is still one big monolith.
- Micro frontend apps: The success of microservices architecture on BE inspires a similar concept on the frontend as micro frontend architecture.
Monolithic vs micro frontend architecture
In monolithic architecture, the front code resides in a single SPA. This results in high code coupling which slows down feature development, experimentation, and maintenance. Monolithic architecture also has high communication costs as teams have to spend more effort on coordination to avoid stepping on each other’s toes.
In micro frontend architecture, multiple small FE apps work together to provide a seamless user experience. Each MF is small and has well-defined scope and boundaries. MF apps are deployed independently and owned by small cross-functional teams.
Microservices vs micro frontends
Let’s take microservices descriptions from aws and see how they apply to micro frontends.
- Autonomous: Each MF can be developed, deployed, operated, and scaled without affecting other FE apps. Any communication between individual MF apps happens via well-defined URLs. MF apps do not share any of their code or implementation with others. Reusable code is kept small and shared as node packages.
- Specialized: Each MF is designed for a set of capabilities and focuses on solving a specific problem.
Benefits
- Agility: Owned by a small independent team who understands context better which results in short development time.
- Flexible scaling: Each MF app can be scaled independently to meet customer demand. Enables teams to pick the right size infrastructure and rendering strategies based on their KPIs/SLAs.
- Easy Deployment: MF apps have fully autonomous CI/CD pipelines. This enables easy rollouts, rollbacks, low cost of failure, more experimentation, and accelerated time to market.
- Technological Freedom: While microservices promote picking the right tool for the job, this idea is more controversial with MF. Having multiple frontend frameworks is costly to maintain in long run.
- Reusable Code: This benefit of microservices does not work for MF. There are attempts to build MF at the component level but there is still a long way to go before these will get wide adoption.
- Resilience: MF independence increases resistance to failure.
Why micro frontend might not work for you
- You are in the early stages of your product. In this situation, a monolith is more economical and efficient. Only adopt a micro frontend when you start experiencing growing pains.
- MF results in increased complexity in infrastructure, hosting, deployment pipelines, and error tracking. If your team lacks skills in automation and infrastructure as code then MF might create more problems for you.
The current state of tooling
There is no widely adopted solution for micro frontends. Most solutions listed on awesome micro frontends are either proof of concepts or experimental. You might have come across module federation which is a WebPack plugin for MF. I consider these solutions risky and won’t recommend using them.
SPA architecture is widely adopted and well-understood. It is low risk and thus a safe bet for building MF apps.
Implementation approach
- Start with a SPA monolith. Break monolith into small SPAs one at a time as you start experiencing growing pain and scalability issues. If you are using NextJs then you can utilize the Multi Zones feature to split monolith code into multiple zones that are combined into a single SPA during the build.
- Use a monorepo architecture to have a single source of truth for source code.
- Stick with one FE framework and learn to work with its limitations.
- Minimize share code between MF apps. Any code sharing should be done as node packages.
- Adopt a shared UI component library for a consistent look and feel across all MF apps.
- Use URL parameters to pass the state between MF apps. Try to limit the passing state and minimize the use of browser session/local storage.
- Host MF apps on the same domain to simplify authentication.
- Consider using Domain Driven Design to decide on MF scope and boundaries.