gravity9 System Architecture Guide: Micro-frontend Architecture
07 May 2024 | Michal Jach, Łukasz Gonciarz
Architecture is a vital aspect of all systems, and applications, serving as a blueprint for engineers which defines behaviour and structure. There are numerous architectural patterns out there and they can be used on different levels of a system – a single system can use multiple architectural patterns!
As a digital consultancy, gravity9 has a rich history and heritage of development, picking the best architecture for the job.
In this series of articles, we’ll introduce some of the most popular system architecture around. We’ll look at why they’re popular, where they’re useful, and where they’re less useful.
What is Micro-frontend Architecture?
Micro-frontend Architecture extends the concepts of Micro-services (where complex applications are broken up into smaller, self-sufficient units that can be managed independently) into the frontend (or UI) world. The current trend is to build a feature-rich, powerful browser application that sits atop a micro-service architecture. Over time the frontend layer, often developed by a separate team, grows in size and becomes more difficult to maintain: we call it a Monolith. As we’ve covered in other articles, designing complex systems as a Monolith is usually easy at the start, but quickly becomes hard to maintain as that system grows and evolves.
The idea behind micro-frontends (sometimes called Microfrontends or Micro Frontends), unlike a cumbersome Monolithic approach, is to have a number of features of a large frontend layer which are broken down and owned by independent teams, making them easier to manage. Each team has a distinct area of business, or “mission” that it cares about. A team is cross-functional and develops its features end-to-end, vertically, from frontend down to middleware, backend, and infrastructure. Micro-frontends allow you to start with a small working system (bound to a business subdomain) and evolve. Mentioned UI parts can be used in multiple ‘host applications’ (“shells”, which are entry point and hosts micro-frontends within) simultaneously.
Below is a high-level overview of what a micro-frontend architecture might look like:
Here we have an example of what a micro-frontend might “be” in the form of a single-page application using micro-frontends.
We’ll cover the advantages and disadvantages of micro-frontend architecture shortly, but it’s worth noting at this point that everything in software architecture comes with a cost. In the course of our own project work with micro-frontends, we’ve encountered challenges with large bundle sizes, the duplication of dependencies, and sharing contexts.
(Especially) when working with React, you ought to create a shared space where micro-frontend components can interact, send, and receive data. To solve the challenges mentioned above, we created a Message Bus implementation, as well as shared runtime contexts. Further steps were taken to optimize bundle sizes, including sharing dependencies at a top level.
Although we note these challenges for your reference, everything is solvable!
Micro-frontend Architecture Advantages.
Below we take a look at key strengths of utilizing a micro-frontend approach, with customization and flexibility becoming clear benefits.
-
Independence: Each micro-frontend operates independently of others, enabling teams to develop, test, and deploy their features without impacting other parts of the application.
-
Scalability: Micro-frontend architecture enables horizontal scalability, allowing organizations to scale individual features or components independently, based on demand.
-
Decomposition: The frontend application is decomposed into smaller, more manageable units, making it easier to understand, develop, and maintain, than alternatives like a Monolith.
-
Technology Agnosticism: Different micro-frontends can be developed using different technologies, languages, or frameworks, allowing teams to choose the best tools for their specific requirements. This allows alternative solutions to unique challenges and needs, however in our experience it’s generally preferable to work with a single framework (like React) across the board.
-
Reusability: Components and features within micro-frontends can be reused across different parts of the application, promoting code reuse and reducing duplication. If the architecture is done properly, we can leverage having single instances of common services at a top level (e.g. routing, messaging, and security).
-
Isolation: Micro-frontends are isolated from each other, minimising the risk of cascading failures and allowing for easier debugging and troubleshooting. This also allows additional resources to be allocated where needed to speed support or growth in specific areas.
-
Incremental Modernization: With isolated components of an application, you can gradually modernize without the need to completely rewrite (that application) all at once. Legacy components can be replaced or augmented with modern micro-frontends, allowing you to modernize your application incrementally while minimizing downtime and disruption to existing functionality.
Micro-frontend Architecture Disadvantages.
Next, let’s look at some potential disadvantages of micro-frontend architecture. The headline pitfalls are increased performance demands and resource overheads, added complexity challenges, and potential additional training requirements.
-
Complexity: Managing multiple independent frontend applications adds complexity to development, testing, deployment, and monitoring processes. Coordinating updates which break the interface to common services with the host can be difficult (other types of changes are 100% independent), especially as the number of micro-frontends grows.
-
Increased Overheads: Each micro-frontend requires its own infrastructure, build pipeline and deployment process. This can lead to increased overhead in terms of infrastructure costs, maintenance, and DevOps complexity.
-
Cross-cutting Concerns: Handling cross-cutting concerns such as authentication, authorization, routing, and state management becomes more complex in a micro-frontend architecture. Ensuring consistent behaviour and user experience across micro-frontends can be challenging if not done right.
-
Rising Performance Demands: Micro-frontend architectures can introduce additional HTTP requests and JavaScript bundles, potentially impacting the performance and load times of the application. Careful optimization and bundling strategies are required to mitigate this.
-
Communication Overheads: Communication between micro-frontends, especially when they need to share data or trigger actions across boundaries, introduces additional system demands. Implementing efficient communication mechanisms such as events, APIs, or shared state management can be complex and error-prone.
-
Learning curve: Adopting micro-frontend architecture may require that incumbent teams familiarize themselves with new design patterns, tools, and best practices. This can be a steep learning curve, particularly for teams accustomed to traditional monolithic front-end architectures.
Although the cost of a micro-frontend architecture may look steep, it needs to be weighed against the impact of not adopting this more flexible pattern vs. a monolithic approach and the potential growing pains that brings. Many of these challenges can be planned for and mitigated if a micro-frontend approach is implemented correctly.
How Does gravity9 Work with Micro-frontend Architecture?
Implementing micro-frontend architecture is a common preference as part of larger projects of application modernization which gravity9 has made possible. In this example, our client is a large operator in the United States’ property rental market who engaged gravity9 for a vast overhaul of legacy systems, as well as the introduction of new bespoke digital functionality.
Duplication, Team Organization, and Structure:
In gravity9’s initial scoping and requirement gathering we uncovered UI elements which were duplicated within multiple applications (for example: Hamburger navigation menus which have the same look, feel, and functionality). These were extracted as separate projects with their own repository, pipeline, and hosting). Multiple teams were formed which owned particular elements of the UI, making up a micro-frontend pattern, who communicated with each other.
Technology Stack:
To rapidly accelerate development and harness the best tools available, our architecture team created a custom Webpack plugin based on Module Federation, which is plug and play and straightforward to implement. It has multiple advantages and additional features like:
-
It’s easy to conduct native imports (import micro-frontend from ‘…’).
-
Dynamic runtime configuration (we use this extensively to serve different configurations in different environments without the need for redeployments).
-
It’s straightforward to leverage bootstrapping without the need to play with deeper Webpack internals.
-
It is possible to conduct hot module reloading between micro-frontends, this means only those modules which have changed will reload – a more efficient approach than reloading the entire frontend.
As a result, gravity9 was able to develop and provide a micro-frontend based solution which can effectively scale and evolve to suit the needs of the client, doing away with messy legacy code and cumbersome architecture.
An Example Integration:
Using our state-of-the-art library, we can easily bootstrap and deploy new micro-frontend projects. Here we’ll provide an example specific to React. Note in this example @gravity9/microfrontends
NPM package is private and shared across gravity9 internally.
-
Initialise the standard React application using
create-react-app
(you can also use any other configuration based on Webpack). -
Use Craco to easily access Webpack configuration and add our plugin (create-react-app hides Webpack configuration by default):
-
Edit
config.json
like so:
-
Your micro-frontend is ready! Next, edit
config.json
inside your host app to point to your micro-frontend:
- That’s it! You can now easily import it wherever you need.
Ready-Made Solutions.
These ready-made libraries and frameworks provide an excellent starting to understand and develop an off-the-shelf micro-frontend based system. We recommend reviewing them to understand how a real-world solution might look, and for basic projects they are useful tools! As with any such solution, they lack the customisation a bespoke implementation can offer.
-
Single SPA is a very basic and ready-to-use micro-frontend library. It is a handy solution for cross-browser management of independent modules, which is key to implementing micro-frontends.
-
Podium is a gravity9 team favorite. It’s a very powerful “all-in” server-side micro-frontend framework.
-
Luigi-Project is an “all-in” Micro-frontend library for enterprise-level applications. It has a built-in solution for authorization, navigation, settings, API, and localization.
-
Frint.js is a little different. Code is loaded from separate bundles, and you need to follow a specific app structure. It does handle routing, dependencies, and more. The project also supports RN and Vue via additional packages, but it is mostly documented and tested for React.
Is Micro-frontend Architecture right for YOU?
The benefits of a well implemented micro-frontend architecture are numerous and, in our opinion, far outweigh the challenges of developing and running one. This is especially true for mature and more complex systems which start to become increasingly cumbersome and problematic to evolve under a more monolithic approach. However, these gains must be weighed against the resource and skill costs required to leverage them, for smaller and new systems, a monolithic approach may prove preferable after all!
Ultimately the best fit depends upon your specific circumstances and at gravity9 we’re in an ideal position to advise you.
The concept and shape of micro-frontend architecture is not especially new, in fact it’s been a topic of discussion among frontend-focussed communities for some years and a number of different approaches have emerged. Having implemented numerous micro-frontend-based systems ourselves, gravity9 understands the challenges and potential pitfalls – and how to overcome them and ensure a successful process of modernization for you and your systems. With the right choice of technologies and a partner with the experience to leverage them, you can count on being set up for success!