Micro frontends architecture? What are micro frontends?
Micro frontend architecture means turning a web frontend application into a set of independent applications (life cycle, complexity, technology) that coexist and communicate on the same site.
The aim of micro-frontends is in line with that of microservices: to fragment complexity so as to have isolated, specific, maintainable and continuously deployable code, each independently of the others.
In a nutshell: an architectural style in which independently deliverable front-end applications are combined into a larger whole.
What for?
Some companies struggle to maintain their web applications for a variety of reasons:
- Outdated technologies
- Test batteries are not enough to secure the application: a change in one function leads to a regression in other functions…
Finally, the slightest change becomes a complex and risky task.
On the other hand, business demands and user expectations are constantly increasing.
You might think that starting an application from scratch would be the best solution. But of course it’s not that simple:
- It’s expensive
- It takes a long time
- Functionalities that have already been developed (sometimes over years) and that work may no longer work
- And finally, there’s no guarantee that the new application will offer any real added value. Will it live up to expectations?
This is where micro frontends come into their own:
- Code bases are smaller, more consistent and therefore more maintainable
- The project can be organized into separate, autonomous teams
- It is possible to upgrade, update or even rewrite parts of the interface in a more atomic and incremental way.
In short, gradually develop the application, brick by brick, while continuing to generate traffic.
The main principles of micro frontend architecture
Independent deployment
The ability to deploy micro-frontends independently is essential, as it reduces the scope of a deployment and therefore the risks.
Each micro-frontend must have its own continuous delivery pipeline, which builds, tests and deploys it right through to production.
We should be able to deploy each micro frontend without worrying about the current state of other code bases or pipelines.
It doesn’t matter if the old monolith follows a fixed, manual, quarterly release cycle, or if the team next door has pushed a half-finished or broken feature into its main branch.
If a given micro-front-end is ready to go into production, it should be able to do so.
Autonomous teams
Another advantage of decoupling codebases and release lifecycles is the tendency to create entirely independent teams, which can be responsible for a section of a product.
Teams can have full ownership of everything they need to deliver value to customers, enabling them toact quickly and efficiently.
For this to work, our teams need to be trained around vertical slices of business functionality, rather than around technical capabilities.
A simple way is to cut the product according to what end-users will see.
In this way, each micro-frontend encapsulates a single page of the application, and a single team handles it from start to finish.
Micro frontends architecture in practice
What is a front end today?
For the most part, it’s a user interface built using HTML/CSS/JS technologies.
On the javascript side, the “in” frameworks are generally Angular, VueJs, React (Svelte?).
Integrating content such as a YouTube video into your application via a iframe
tag is the beginning of a micro-front end.
The video is then an autonomous brick forming an integral part of the application.
The iframe is not, however, a recommended solution for organizing your application into micro frontends, for a number of reasons:
- Incompatible with Responsive Design
- Safety issues
- Difficulty with referencing
- Difficulty communicating with other parts of the application due to the unique window.postMessage() feature.
Web Components
Web Components are a set of several technologies that enable the creation of reusable custom elements, whose functionality is encapsulated outside the rest of the code and can be used within web applications.
Unlike React, Vue, Angular or any other JavaScript framework, these components are (finally!) natively supported by the majority of browsers.
In concrete terms, a web component consists of an HTML template encapsulated in a Shadow DOM – document nested within the document and “hidden” from the rest of the tree – to which the web component’s scripts and styles are attached.
To inject a web component into your application, all you need is a custom tag in the HTML code and a script using the Custom Elements API to define and inject our micro frontend into this tag.
<html>
<head>
<script src="https://mon-site.fr/web-components.js" async></script>
</head>
<body>
<react-web-component></react-web-component>
<angular-web-component></angular -web-component>
<autre-web-component></autre-web-component>
</body>
</html>
- Library for Vue.js : @vue/web-component-wrapper
- Library for Angular : @angular/elements
- Library for React: Direflow
Benefits
Web components are reusable and adaptable to almost any use case.
They can be encapsulated in a Shadow DOM, which protects them from any possible style conflicts.
Web components can be nested within web components.
Disadvantages
Web components are generated on the client side by the associated JS script.
As a result, it’s difficult to make them server-side for SEO purposes, for example.
Encapsulation via Shadow DOM currently poses unresolved web accessibility problems.
Server-side rendering: Node.JS / Express / EJS
More and more applications are usingServer-Side Rendering to couple the dynamic display of client-side rendered applications with the natural referencing offered by MPAs (Multiple Page Applications).
Today, the best-known frameworks are Next.js (React) and Nuxt.js (Vue).
Thanks to Express’s EJS templating module, you can compose server-side rendered applications on the same page.
To do this, each application living at a different address is queried, assigned to an EJS variable, then rendered according to templates.
/* index.js */
server.get("/", (req, res) =>
Promise.all([
get("https://adresse-react.fr"),
get("https://adresse-vue.fr"),
get("https://adresse-angular.fr"),
get("https://adresse-ember.fr")
])
.then((responses) => {
res.render("index", {
react: responses[0],
vue: responses[1],
angular: responses[2],
ember: responses[3],
});
})
.catch((error) => res.send(error.message))
)
<!-- index.ejs -->
<html>
<head>...</head>
<body>
<%- react %>
<%- vue %>
<%- angular %>
<%- ember %>
</body>
</html>
Benefits
Natural referencing is optimized because the first display of the site and its micro frontends in the browser does not require the execution of JavaScript, which takes longer to load than HTML and CSS, and is not read by the majority of web crawlers.
Disadvantages
We’re back to the classic MPA problem: the automatic refresh when a page changes is a hindrance to smooth navigation, and therefore to the user experience.
Framework Single SPA
Single-SPA is a technique in a class of its own, since it is a framework dedicated to the implementation of micro frontends based on several SPAs (hence the name).
It’s a “meta-framework”, a category emerging with the development of micro-frontends, aimed at the need to centralize lifecycle management and inter-application communication.
The Single-SPA principle is as follows:
- Each micro frontend implements 3 methods – bootstrap, mount and unmount – enabling the application to be created, attached to the DOM and removed from it, respectively.
- A “root” application (root-config) orchestrates the positioning and dynamic display of applications, based on routes.
Benefits
The main advantage of Single-SPA is its ability to migrate an existing SPA application to micro-frontend, thanks to the libraries it offers.
Disadvantages
Documentation isn’t yet easy to get to grips with, and training courses are a bit expensive for a POC.
We’re still seeing unresolved display bugs in some cases(the unmount of Angular micro frontends).
As the framework is based on SPAs, server-side rendering is not available.
And then
This article ends here, but there’s a lot more to say about this type of architecture.
In the next article, we’ll take a closer look at how these applications are put into practice with three important questions:
- How do you communicate between the different parts of such an application, potentially built using different technologies?
- What’s the best way to communicate with an API?
- What testing strategy can be put in place to ensure the coherence and smooth running of the whole?