Micro frontends have become a hot topic in the tech world in recent years. When I started researching and applying this technology, it turned out it wasn't as simple as I had initially thought. That’s mainly because there are so many advanced concepts we need to deal with to build a good micro frontend.
But where do you even start? There are many tutorials and articles on the internet on micro frontends. However, I could not find any articles covering everything I needed, explaining the basics of micro frontends, their purpose and the best tools to build one.
So, I decided to write this post to give a comprehensive overview of micro frontends that covers all core aspects of the technology.
What is a micro frontend and why do we need it?
The term micro frontend was introduced in 2016 and its usage has continued to gain in popularity ever since. Basically, it extends the concepts of micro services to the frontend world. As you know, a multi-page app/single-page app is built by combining many blocks/components. Over time, the frontend layer is often developed and maintained by different teams, causing it to grow and become more difficult to maintain. These concerns are exactly why many companies continue to struggle with monolithic frontend codebases.
To deal with these issues, the idea of micro frontends was born, allowing different micro-apps within a larger app to have their own frontend. This brought with it a lot of advantages:
- They allow teams to work independently and just take care of their distinct area of business.
- They allow us to work with a smaller and maintainable codebase.
- They enable us to upgrade or even rewrite the path of the frontend easily and safely, since each application will contain less code and not depend on other apps.
- They can be deployed autonomously without fear of impacting another team.
- They allow us to easy scale individual services, with each application using its own scale requirements.
How do you build a micro frontend?
Now we know what a micro frontend is, so let’s take a look at how you build one. This is where it can get a bit tricky. There are a lot of advanced concepts we need to deal with, and now I will walk through each challenge one by one.
Integration approaches for a micro frontend
- Iframe is an old approach to use single-page with multiple inner applications, each one in a different iframe.
- Webpack Module Federation is a Javascript architecture invented by Zack Jackson. This architecture allows a Javascript application to dynamically load code from another application and, in the process, share dependencies, which allows for less code duplication in the application. It only works on webpack 5.
- Import-map is a strategy using the single-spa framework, allowing control over what URLs get fetched by Javascript import statements and import().
- Micro-Frontend using Web Components, where each application can be represented by a custom HTML element.
Selecting the right framework for your micro frontend
There are eleven micro frontend frameworks. I don’t want to list all of them here, so I only cover the framework I find best suited to help us build great micro frontends.
- single-spa: single-spa is a framework for bringing together multiple JavaScript micro frontends in a frontend application.
- Luigi: powered by SAP, it uses iframes to build micro frontends.
- Piral: Piral enables you to create a modular frontend application that is extended at runtime with decoupled modules called piletsleveraging a micro frontend architecture.
- Frint: a complete framework that delivers routing, state management, server rendering and other features to micro frontend architecture.
- Bit lets you compose and manage frontends from independent components. It’s probably the most popular and production-ready solution on the list.
- Webpack 5 and Module Federation: Multiple separate builds form a single application.
I suggest that you use webpack 5 and module federation to set up micro frontends since it makes the code independently deployable between applications and makes code sharing and state management easier.
Styling and theming a micro frontend
Share a Style Guide
As we all know, the UI of the parent app is made up of multiple micro-apps, so we have to ensure user experience and look and feel are consistent. Therefore, I want to emphasize that the style guide and design system must be shared between team.
How to manage style in micro frontends effectively while improving performance
We can share the same style at the global level. However, sharing CSS globally can introduce risk to the class conflict.
- We can apply a newer approach by using CSS-in-JS (library styled-components) so that we can add, change, and delete CSS without any unexpected consequences. This sounds great, but unfortunately, when I did a comparison, I noticed that the styled CSS-in-JS implementation appeared to take about 40% longer to render the critical path of a web page, this is a critical issue that we can't ignore. This approach leads to JavaScript bundles being heavier – especially when we access the web app on devices and from regions with slower internet connections, the large JavaScript bundle will lead to slow downloads and blocked rendering
So, what do we do to solve this issue? This can be accomplished with some different approaches:
- Using BEM (Block Element Modifier) is a methodology that helps you to create reusable components and code sharing in frontend development.
- Using MiniCssExtractPlugin to extract CSS into separate files to reduce the size of your JavaScript bundle file. It creates one CSS file per JS file that contains CSS and supports on-demand loading of CSS. This is still not enough, because if we load external stylesheets as async, it leads to a flash of unstyled content. But if we load style as synchronized, then it blocks the first paint of a webpage. That means we only use non-critical CSS as external stylesheets and download as async, and deliver critical CSS as inline style at the head tag.
Manage theming of your micro frontend
In the past, we have often developed a web app intended to be used by dozens of brands - which all require different colors and branding. For some requirements, we need to switch between themes instantly on the webpage without refreshing the page, but for others, we only need to set up a theme from initial load. So how do you control the theming in a micro application? Let’s walk through some options:
- Using CSS custom properties as variables: This is the new CSS feature known as Custom Properties. If we have a lot of themes, we should not define override variables for each of them because it leads to a large CSS bundle. Therefore, we should re-assign variable values with JS.
- Using mutating state: In a reactive framework, we can store CSS properties such as colors, background etc. as a part of state. Then, we can fill the state value of properties to class and use style bindings or event-scoped CSS.
Shared component libraries
In micro frontend architecture, we need to share some common UI components across child and parent applications. Some candidate components for sharing are buttons, checkboxes, labels or selections. We can also share more complex components such as suggestions and pagination. However, make sure that your shared components include only UI logic, not business or domain logic. When domain logic is put into a shared library, it introduces a strong coupling across applications and increases the difficulty of change.
Furthermore, we want a solution that can share dependencies. That means we should never load the same dependency twice.
In order to deal with the problems above, we can use Webpack 5 and module federation. This plugin helps expose and share components in both build time and run time and is considered to be the most popular approach.
State Management
State management can be challenging when it comes to micro frontends. Which state manager to use, what state to store between the different micro frontends, how to let them talk to each other, how to architect it all – there are many questions to be answered. We can share states using 4 different methods:
- Web Workers
- Props and callbacks
- Custom Events
- Pub Sub library (windowed-observable)
I prefer windowed-observable because it is simple to set up, pretty customizable, isolates namespace events, and offers extra features to retrieve dispatched events.
Handle routing
I strongly recommend that each team building a micro-app is responsible for routing within its own web app. If one team updates a router map, it will need to talk to all teams.
Conclusion
In this article, I covered a number of technical considerations to help you design and develop your micro frontend architecture.
There are many ways to accomplish the same goal as long as your app has to meet some criteria like Core Web Vitals scores, UX Style Consistency, Cohesive User Experience, or
Smooth Inter-App Transition.
Which style of creating micro frontends do you prefer? Let us know below or contact us today to find out more about how we can help you build your micro frontend.