Micro Frontends in Action
Let us implement an app composing MFEs built in React & Angular
Before getting into code lets take a look at what problem we are trying to solve with Micro Frontends.
We have seen the paradigm shift of how we organize code & ourselves in the past.
When we realized the fact that managing services (that serve the UI) as a monolith is not the right thing to do, we split that up into independent, manageable microservices.
Problem: This has created a monolith on the UI side of the code. A single front-end team handling/consuming changes from all the microservices create a monolith in the overall system. Now that the services can be developed & deployed independently & at a faster speed, the capability of testing, releasing these services end to end does not match the speed of development.
- UI framework migration is not easy.
- Monolith UI in terms of the team or the codebase.
- No end to end feature specific team.
- No easy amalgamation of components written in different UI frameworks.
Solution: We organize ourselves & the code into end to end teams with micro frontends. Based on the use cases we have multiple end to end teams which take care of the service layer as well as developing the UI for it.
This allows us to have multiple UI components(thus use cases) in build & release pipelines together. With this approach, the updates on the backend or the service layer can be deployed in parallel & users can get to see the changes quicker. Moreover, since the micro frontends will have their own scope of error, debugging and a separate code base the maintainability of code & sharing of common components improves.
Ways to implement micro frontends
We are already doing it in many ways. When we consume a frontend component from an external library, that is a micro frontend for us since it has its own development & release life cycle.
When we split up components into separate code bases & make them available as micro frontends, the responsibility of composing them together still lies with the container app. When we allow our app to compose multiple micro frontends from various sources we can also leverage a fact that they can be developed using a UI framework that is different from others in the ecosystem.
So based on this we could have two ways of implementing micro frontends:
- Build time integration: This is the same as what I just mentioned above. We usually plug-in components from third-party libraries either as bundles injected as npm modules. So if we start writing the components as npm modules published in public or some private repo & plug those in, in our container app, such code organization will still be called as micro frontend architecture.
- Run time integration: This is when we inject micro frontends into our container app dynamically either in one shot or on-demand through lazy loading. This can be done in multiple ways:
Iframes: Having different components render in a different iframe is the easiest solution but it doesn't seem scalable. Moreover, the inter iframe communication done through postMessages will need you to implement your own PubSub mechanism.
Component Composition: Inject micro frontends into the container app through dynamically loading component bundles.
See the full source code here: https://github.com/gauravbehere/micro-frontends
In the example above I am injecting three micro frontends served from localhost from different ports. In reality, in production, they will be served from different servers.
What these scripts contain is an independent UI component/micro frontend bundled into a single file. (I could have done a better job in renaming the bundles)
In the example above I have the following micro frontends:
- Pagination: Developed in React, served on port: 6001
- Gallery: Developed in React, served on port: 6002
- Page Number: Developed in Angular, served on port: 6003
Container app composes all the above components and is written in React and served on port 5000.
Please clone the repo https://github.com/gauravbehere/micro-frontends, follow the instructions & run the demo to see this composition in action.
See how clicking on next from a react component we let the other React component & the Angular component know.
How does the stuff work?
How do we have React & Angular micro frontends working together?
Now that you have seen the micro frontends in action let us see how does this all fit in. It is high time we talk about Web Components now.
In the example above we are exporting the page number component written in Angular into a standard Web Component.
This article helped me in doing so: https://medium.com/@suwigyarathore/angular-element-as-a-web-component-6e77a1e1b4a7
Web Components allow you to have a standard way of developing components that are framework agnostic. Web components interact with each other using the classic DOM APIs & the change of attribute values (props in React terms). Dispatching custom events that other components will be listening to, message passing can be done. The container app can modify the attribute/prop values to pass on data to web components.
Read more about web components here: https://www.webcomponents.org/introduction
Good Reads
Wrapping Up
In my example, I have the container app written in React which could have been a pure web component too. With this, we open endless possibilities & combination of components written in different frameworks. To have the capability of loading micro frontends when you need, you can also have a loader that loads the MFE bundle. That said, this is just another way to implement micro frontends. We could also do such composition when rendering on the server-side. I will be glad to hear about your experience in implementing micro frontends.