Introduction to Micro Frontends: General Concepts, Advantages, Disadvantages and a Case Study
What is a micro frontend? Let me explain them in the context of microservices.
A microservices architecture consists of discrete applications or services that are loosely coupled. The development of one microservice has no dependencies on another microservice.
They can be managed and deployed independently of one another. Similarly, micro frontends could be thought of like microservices but on the front end.
A micro frontend is a set of techniques, approaches, strategies, and recipes for building a modern web app, which may be developed by several teams independently, including on different tech stacks and frameworks.
Micro frontends call for the segregation of your application into small, independent sub-applications. A micro frontend could be a separate page or a separate view in a web app. Different teams might be responsible for each micro frontend. Each team independently chooses the coding style, technologies, and approaches for their micro frontend.
What are the advantages of micro frontends?
Micro frontends have several advantages.
Micro frontends are technology agnostic: the programming languages, frameworks and libraries you select can be unique to each micro frontend. So, each team can work on a micro frontend to solve a business need and teams don’t need to concern themselves with which technologies other teams are using.
The logic or behavior of different front ends doesn’t need to be dependent on each other. This makes maintenance easier because a change to one micro frontend doesn’t necessarily require changes to another.
Independently deployed, they result in faster releases
Micro frontends are independently deployed, which removes the complexity of scheduling dependencies. Since micro frontends are owned by small teams, releases can be managed by a separate CI/CD pipeline and done much faster, since there are no breaking changes or dependencies.
What are the disadvantages of micro frontends?
As with most new technology, micro frontends inherit some key challenges with adoption:
- Additional operational overhead with integration in exchange for flexibility
- A change is needed in the developer mindset to correctly work with micro frontends, which is not simple and might take time
- An emerging developer community, which limits the response time for some of the answers
- No established best practices yet due to a wide variety of implementations
Another disadvantage has to do with a performance impact.
Being technology-agnostic might have performance impacts
There are many technology combinations front-end developers may use in micro frontend applications such as plain HTML/CSS, React and AngularJS. Some developers might want to use GraphQL, while others choose to use REST.
If we build these micro frontends into one main shell application, all of those libraries and frameworks will be downloaded at the same time. Now it carries a certain performance overhead and product risks. This may be mitigated by implementing lazy loading.
General concepts of micro frontends
Now let’s discuss some of the main components of micro frontends.
The application shell
The application shell is the main application, most likely a thin application, that micro frontends integrate into. Each of the micro frontends is injected into the application shell. Application shells should not contain any business logic. Instead, all the logic should remain within the micro frontends.
Communication between micro-frontends
Loose coupling demands that there should not be a need for any contracts between micro frontends. However, if there is a pressing need for communication between them, then the application shell helps facilitate it. The most common pattern would be event-bus.
Event-bus is the communication channel built within the application shell that listens to events and triggers actions, which other micro frontends subscribe to. It helps in one micro frontend communicate with another.
This blog post from DEV makes a decent attempt at explaining this communication pattern in the context of micro-frontend.
How to add a new micro frontend to the application shell?
There are several methods for adding micro frontends to the application shell.
In this approach, every micro project stays in a separate package in a separate repository. Each micro frontend acquires a new version, is deployed to a local repository manager (such as nexus) and is built into and deployed with the application shell and other dependencies.
Iframes are one of the fastest ways of implementing the integration of the micro frontends. It is the only component that gives us absolute isolation from other micro frontends and from the application shell because an application lives independently within the iframe.
It can communicate with the outer world, from where it was downloaded, solely via the event-bus. It can also obtain information via the URL indicated when we use the query, (e.g., a session ID).
Webpack Module Federation
Webpack Module Federation helps us share code with different applications.
Let’s take an example depicted below:
Here we can see that we have three build files: navigation, main and basket. Main is the application shell and there are two micro frontends. Each of them has its own content which may be used in the application shell.
As part of webpack config, the configuration is maintained to indicate the data and the corresponding build files. Webpack in turn processes the needed pieces of the built code in such a way that we may import and use components from one micro frontend in another micro frontend and of course, in the application shell.
This works well as is evident in our example that Header can be imported from the nav and MagicButton can be imported from the basket.
This approach, however, has a few drawbacks. The main one is that the webpack module generation is still very much evolving. Among other complications, for example, webpack module federation does have some compatibility issues with a few applications.
Web Components. Custom Elements.
Web Components allows us to create custom elements with the HTML standard logic. Modern frameworks use a similar principle. There was a time when people said that web components would either replace frameworks or would completely merge into them.
So, it turns out that we can use a component approach without using the framework. It’s great! A Medium post by Anjali Verma does a very good job of explaining this in further detail.
How to organize micro frontend code
When considering micro frontends it’s important to understand such things as Monorepo and Multirepo. In the Monorepo approach, all the micro frontends, the application shell, shared components library, utilities, etc. stay in different folders, but in a single repository and may be delivered differently. If you have several teams working on these micro frontends, then crossing over is possible.
Multirepo is a less common way of structuring micro frontends, but it is a logical way to organize things. Each micro frontend lies in a separate repository, as do application shells, libraries and utilities. Import maps can be used to connect the micro frontends to the application shell. For the case study referenced later in this article, the Lohika team decided to use multirepo after understanding the client’s needs. It has in turn helped the client’s teams to structure their code base and manage the releases, minimizing interdependencies.
Case study: a micro frontend project at Lohika
Our client is a leading provider of project management software. The company brings together social collaboration and project management to help every organization go from idea creation to execution efficiently, effectively, and faster than ever before.
Another modern application, built using more modern programming languages, lived separately from the main monolith app. This modern application was integrated into the legacy application into separate pages using iFrames. The client’s development team was already facing many challenges maintaining and enhancing the applications, owing to its mammoth structure and integration.
There were other complementary applications that were developed by separate teams. The ask was to integrate these applications into the modern application, at several places and in different modules.
The Lohika team was assigned this task to combine all these components into a single UI.
A new design was specified, which required the integration of several widgets. The team needed to integrate these widgets into one big, powerful UI. Micro frontend was chosen as a method for implementation. Our team utilized event-bus for communication between the micro frontends.
Why would we need that?
It was needed to integrate applications without merging one code into the other (i.e., bringing the code from one repository into the other). Each one of them had its own routing and other accompanying elements.
The goal was to show multiple widgets without mixing the existing micro frontends. An application shell was created and integrated with micro frontends, leveraging the concepts of webpack module federation.
With this implementation, the Lohika team eliminated the need to break up the monolithic application.
Micro frontends are a new and powerful way to structure applications and code that is well-aligned to engineering org structures. In the case study referred to above, Lohika started from two teams working on the two parts of the application, and today, after two years from the start date, there are five teams working on several micro frontends in different parts of the application.
We continue working on the modernization of the old application along with providing the new functionality. We can say with certainty that the chosen way was the best possible for this case study.
And finally, before we conclude, let us summarize a more general approach while considering micro frontends.
- Reusability is a nice “side effect” not the target
- Arrange your micro frontends around business functionality
- Structure your applications around autonomous teams
- Don’t force this architectural style just because it is new
- Don’t measure your micro frontends by the size of the code base
Do reach out to us for any suggestions, or if you need a second opinion with implementing micro frontends.