Micro Frontends – Use a microservices approach in frontend development
In today's online world, we come into contact with various web apps. From small tools and projects to portals and cloud applications that include a whole set of different functionalities and options. When developing large and complex web apps, development teams usually face the same challenges. As an option that would solve these problems, micro frontends architecture began to appear.
The architecture began to be discussed and analyzed in more depth around 2015. In 2016, an idea was presented in Technology radar.
The idea is based on the Microservices architecture, which describes a way to divide a monolithic backend into several smaller logical units that work together. One of the first larger companies that decided to use micro frontends (MFE) architecture was Ikea. Later, this concept proved itself and was used by other companies such as DAZN, Spotify, Soundcloud, Zalando and others.
What challenges can teams face in large projects? For example:
- increasing complexity of the application,
- organizational problems,
- slow onboarding for new team members,
- speed of delivery of innovation to the application,
- independent deployment.
An example of an application that includes several functional parts can be a bank's website. Contains e.g. client zone, internet banking, section for media, section for investors, etc. Each mentioned part represents a logical whole that could exist as a separate application. The idea of MFE is to divide a large complex web application (e.g. Single Page Application) into smaller logical units that communicate and cooperate with each other. Such units represent separate sub-applications (SubApp). The goal is to achieve a low degree of interdependence between SubApps and strive for the greatest possible isolation and logical integrity. Single Page Application
Advantages of MFE
Possibility of using different technology for each SubApp:
- freedom in implementation using the framework, e.g. React, Angular, Vue, ...
- own concept for styling: Sass, Scss, StyledComponents, Tailwind, Bootstrap, ...
Autonomous teams - each SubApp can be developed by a different team of developers who set their own processes, convention, procedures, etc. independent of other teams. Their operation is not directly affected by another team. This includes independence in development, deployment and management.
Isolation of error states - if one SubApp fails, it will not affect the others and the application as a whole will continue to function.
Faster onboarding - imagine new team member will start to work on the development of a SubApp, the complexity of which is much smaller compared to the entire application, if it were built as a monolith. Therefore, he does not have to know all user scenarios, links between logical blocks and the overall idea.
HR possibilities during recruitment - it follows directly on the first mentioned advantage. If the application is not strictly built on only one framework, it is not necessary to strictly focus on only one technology when looking for new people for the project. People with different technological knowledge will find employment on the project: React developer, Angular developer, ...
Development of innovations and new functionalities in the future - thanks to the weak interconnection between individual SubApps, changing/improving/expanding the current implementation is less difficult. Since it does not have an impact throughout the entire application, but only on a specific SubApp.
Disadvantages of MFE
UX/UI consistency - it is necessary to adhere to uniform designs and UX flows throughout the entire application in order to appear uniform.
Code duplication - greater assumption that parts of the code that solve the same problem will be repeated through individual SubApps.
Technological problems - correct setting of the entire project, interconnection of SubApps, debugging and monitoring, use of the same nomenclature for global variables, CSS style overrides, etc. These are all challenges that must be faced when using the MFE architecture. For its successful use, a considerable amount of knowledge about individual technologies and the architecture itself is necessary.
Testing - easier from the point of view of SubApp but more demanding from the point of view of the application as a whole. It is necessary not only to test individual SubApps but also individual integrations between them.
More demanding analysis - to correctly identify the logical scope and what exactly the given SubApp should cover. Also, the communication interface between individual SubApps, so that it is universal, simple and does not force a strong dependence and interdependence of individual parts.
Types of integrations
The skeleton of the entire application built on the MFE architecture is provided by the container. It is a control element that decides when and where the given SubApp should be displayed.
Integration - how and when the container gets access to the source codes of individual SubApps
There are 3 types of integration, how individual SubApps are interconnected with the container and create a functional whole.
Before the container is loaded in the browser, it accesses the source code of the requested SubApp.
Individual SubApps are integrated into the Container as modules (dependencies). The Build SubApp creates a module that is included in the Container and is contained in its resulting build. A change in the SubApp will cause another build and deployment of the Container with the new version of the SubApp to be required.
The integration is easy to set up and understand. The disadvantage is the re-deployment of the Container, with every change (version) of the SubApp that we want to reflect in the final application. It also appeals to a fixed connection Container + SubApp(s).
After the container is loaded in the browser, it gets access to the source code of the requested SubApp.
Individual SubApps run separately remotely on a defined path. The container has defined on which path which SubApp is available. Changing the SubApp version does not require re-deployment of the Container and is reflected immediately. Different versions of SubApp can have different paths defined.
Integration is more complex to setup, but does not require additional deployment of the Container when changing the SubApp. Also, the deployment of the SubApp itself is independent.
Server (Server side rendering)
During container rendering, the server decides whether or not the source code of the requested SubApp should be included.
It stores the SubApps source codes in the CDN and assembles them into the resulting view, which is later served at build-time or run-time. The principles are further similar depending on when the resulting view is served.
Frameworks for MFE
One of the most popular frameworks for MFE. Allows creating and managing SubApps through independent components. Their homepage is an example of how the framework itself works. It uses build-time integration.
It allows you to develop multiple separate builds without depending on the code of other units. Each is developed and deployed independently. It uses run-time integration. Webpack from version 5 offers the option of using the Module Federation plugin.
The principle is that each SubApp can react to events from URL routing and must support actions for bootstrap, mount and unmount. The difference from traditional SPAs is that here the applications must be built in such a way that they can coexist with others. It is not necessary for each SubApp to have its own HTML page. At least one SubApp (Container) must be remotely hosted. It uses run-time integration.
If problems arise during the development of the project that could be the motivation to go the MFE architecture route, it should definitely be considered. It has proven itself in practice and has been implemented by large companies such as Ikea or Spotify. It should be kept in mind that the MFE architecture brings benefits, but also includes pitfalls. It is important that the architect correctly decides which form of integration will be implemented on the project. Care must be taken to observe the principles defined for this architecture and try to cover the entire concept with knowledge so that the project reaches a successful end. The website micro-frontends.org can serve as a springboard to start