In this tutorial, we will learn about Microfrontends, Microservices for the Frontend. Benefits and challenges of microfrontends. Challenges of microfrontend design. Principles for building microfrontends
Microservices are a popular way to build small, autonomous teams that can work independently. Unfortunately, by their very nature, microservices only work in the backend. Even with the best microservice architecture, frontend development still requires a high degree of interdependence, and this introduces coupling and communication overhead that can slow down everyone.
Can we take microservice architecture patterns and apply them to the frontend? It turns out we can. Companies such as Netflix, Zalando, and Capital One have pushed the pattern to the front, laying the groundwork for microfrontends. This article will explore microfrontends, their benefits and disadvantages, and how they differ from traditional microservices.
Microfrontends are what we get when we bring the microservice approach to the frontend. In other words, a microfrontend is made of components — owned by different teams — that can be deployed independently. These components are assembled to create a consistent user experience.
A monolith can be decomposed in different ways. We can split frontend and backend or use microservices on the backend. We can even recreate the frontend as a collection of isolated components managed by different teams.
With a microfrontend, no single team owns the UI in its entirety. Instead, every team owns a piece of the screen, page, or content. For example, one team might be responsible for the search box, while another might code suggestions based on users’ tastes. Additional teams might code the music player, manage playlists, or render the billing page. We add complexity but teams get increased autonomy in return.
Frontend functionalities are managed by different teams, independently deployed, and injected into the homepage transparently to the end user.
Microfrontends offer similar benefits to microservices. Namely, we can scale up development by breaking the frontend code into isolated pieces, for which different teams are responsible. As with microservices, each feature can be released on its own, at any time, with little coordination. This leads to more frequent updates.
Microfrontends enable the creation of vertical teams, which means a full-stack team of developers can own a feature on both the backend and the frontend at the same time.
Fullstack vertical teams are responsible for both the frontend and backend of a feature or component.
Every part of a microfrontend is a deployable unit. This allows teams to publish their changes without waiting for a release train or depending on other teams finishing their work. The end result is that the frontend can be updated several times per day.
Each team can have separate repositories, CI/CD pipelines, and service machines. Alternatively, we can host everything on a monorepo and have a single shared CI/CD pipeline.
The main challenge of microfrontends is creating a fast and responsive client. We must never lose sight of the fact that the frontend lives in an environment with limited memory, CPU, and network, or we risk ending up with a slow UI.
A snappy UI is vital for the success of the product. A recent survey pointed out that “a site that loads in 1 second has a conversion rate 3x higher than a site that loads in 5 seconds”. Every second the user has to wait, money is thrown out of the window.
In addition to all the challenges microservices have, microfrontend design poses a few more problems:
Coordination: with so many moving parts, APIs need to be very well-defined and stable. Teams must coordinate on how different components in the microfrontend communicate with each other and the backend microservices.
There are two complementary methods for rendering a unified UI from separate microfrontend components: server-side and client-side rendering.
Server-side rendering offers faster performance and more accessible content. Rendering on the server is a good alternative for serving content quickly — especially on low-power devices like low-end phones. It is also a suitable fallback mode when JavaScript is disabled.
The webserver assembles the full page from the content provided by different microservices. This serves as the first contentful page. Hydration can then be used to add more dynamic content.
We have a few ways of performing SSR:
So, for instance, we can use SSI to render a page from HTML with this:
<div>
<!--#include virtual="/hello-world" -->
</div>
The virtual
keyword makes the webserver request the content from a URL or CGI program. In our case, we would need to set up the webserver to respond to requests based on the path /hello-world
with a suitable fragment:
<h1>Hello World!</h1>
SSR is used in many web frameworks to render the first screen. Additionally, there are also some interesting SSR-specific utilities like compoxure, nodesi, and tailor.
Client-side rendering builds the page in the user’s browser by fetching data from microservices and manipulating the DOM. Most web frameworks use some form of CSR to improve the user’s experience.
CSR dynamically renders the page on the user’s browser using data provided by the endpoints.
The main tools we have to write loosely-coupled components are Custom Elements. Custom elements are part of the HTML standard. They allow us to create new HTML tags and attach logic and behavior to them.
Custom elements are dynamically mounted and unmounted from the page using JavaScript:
// hello-world-component.js
class HelloWorld extends HTMLElement {
connectedCallback() {
this.innerHTML = `<h1>Hello world</h1>`;
}
}
customElements.define('hello-world', HelloWorld);
Once defined, we can use the new element like any other HTML tag:
<hello-world></hello-world>
In the example, the full page would include a script tag to fetch the JavaScript components:
<!doctype html>
<head>
<meta charset="utf-8">
<title>Microservice Example</title>
</head>
<body>
<script src="./hello-world-component.js" async></script>
<hello-world></hello-world>
</body>
</html>
While most frontend frameworks can be used for microfrontends, some have been designed specifically for them:
Switching to a microfrontend architecture can give our development teams more autonomy, thereby accelerating development. However, the same caveats that apply to microservices are also relevant for microfrontends. We need to have a proven design, which means microfrontends are not a good fit for greenfield projects.
New projects are best served by traditional patterns such as single page applications (SPAs) managed by a single team. Only once the frontend has stood the test of time can we consider microfrontends as the way forward.
Source: https://semaphoreci.com
#microfrontend #microservices #frontend