What is it and why do I need it?
Let’s start with the why part, when the days of single page applications started most applications were considerably small and managed by a single FE team, all was well…
With time, applications have gotten larger and larger, and so have the teams managing them. No need to say much about the problems of having large code bases and large teams…
The term Micro Front Ends has been thrown around a lot lately, offering a concept similar to Microservices where we can split a monolithic Front End application to micro applications that can be loaded into a single container application running on the users’ browser.
Each application can have its own code base, be managed by a business-oriented team which can test and deploy their micro-app independently.
(taken from https://micro-frontends.org/)
While the concept itself sounds promising, actual implementations of it are lacking. Especially ones that can apply to an existing large application.
One possible solution is using the good old Iframe, which offers many advantages as far as encapsulation and independence but is an old technology and suffers from significant scale issues.
Other than Iframes, the term Web component has also been floating around for a while.
Web components are a solution where you can create custom DOM elements that can run independently and provide separation and CSS encapsulation, while this sounds like the right direction, Web components are far from an actual solution. They are more of a concept and the features behind it, such as the shadow DOM still lack full browser support.
At Outbrain we have been facing the issues that most veteran SPAs are facing, we have a huge FE application, with a large team to manage it, and it’s getting rough.
Seeing that there are no outstanding solutions for MFE in the wild we decided to try to find a solution of our own, one that is quick to implement on our current eco system.
We defined several key points that we saw as necessary for any solution to apply as an MFE.
Each micro-app should be capable of running completely in standalone mode, so each team in charge of a given app should be able to run it independently from other applications.
This means each application should be hosted on a separate codebase and be able to run locally on a developer’s computer, and in dev and tests environment.
It should be possible to deploy each service independently to any environment including production in order to allow freedom for the owner team to work without interfering with other teams, If a bug fix needs to be deployed to production on the weekend no other team should have to be involved.
Running tests independently on each micro-app, that way a bug in one app is easily identified and doesn’t reflect on other apps. That said It is necessary to have some integration tests to check the interfaces between apps and make sure they are not broken, these tests should be monitored by all teams.
One to many
We want to be able to use each micro-app multiple times, a micro-app should not care where it runs, only be aware of its input and outputs.
Runtime separation and encapsulation
It is critical that each app is sandboxed in the runtime environment, so apps don’t interfere with each other, this includes CSS encapsulation, JS namespacing and HTML separation.
Common resources sharing
Since we don’t want to have to load large modules like Angular, lodash and CSS styles multiple times in the app it is important for micro apps to be able to share common resource between them, that said, we also want to be able to allow them to encapsulate resources that are only relevant to them, or encapsulate resources that have different versions across apps, for instance app A uses lodash 3 and app B wants to migrate to lodash 4. We don’t want to wait for all apps to migrate before it can upgrade.
There needs to be a decoupled way for the apps to communicate with each other without actually knowing about each other, only via predefined interfaces and API’s.
Since we are not going to rewrite our huge code base, we need something we can plugin to our current system and gradually separate parts that can be managed by other teams.
Finally, Any solution we go for should be aligned as much as possible with the web components concept, even though it is currently just that, a concept, it seems that that is the way the future is heading, and if any solution pop up in the future, aligning ourselves with this will help us adopt future solution.
In the next part, I will go into details about how we achieved this and lived to write about it.
The ingredients for the next part include Angular, Webpack and a couple of tasty loaders.