Book Image

The Art of Micro Frontends

By : Florian Rappl
Book Image

The Art of Micro Frontends

By: Florian Rappl

Overview of this book

Micro frontend is a web architecture for frontend development borrowed from the idea of microservices in software development, where each module of the frontend is developed and shipped in isolation to avoid complexity and a single point of failure for your frontend. Complete with hands-on tutorials, projects, and self-assessment questions, this easy-to-follow guide will take you through the patterns available for implementing a micro frontend solution. You’ll learn about micro frontends in general, the different architecture styles and their areas of use, how to prepare teams for the change to micro frontends, as well as how to adjust the UI design for scalability. Starting with the simplest variants of micro frontend architectures, the book progresses from static approaches to fully dynamic solutions that allow maximum scalability with faster release cycles. In the concluding chapters, you'll reinforce the knowledge you’ve gained by working on different case studies relating to micro frontends. By the end of this book, you'll be able to decide if and how micro frontends should be implemented to achieve scalability for your user interface (UI).
Table of Contents (21 chapters)
1
Section 1: The Hive - Introducing Frontend Modularization
6
Section 2: Dry Honey - Implementing Micro frontend Architectures
14
Section 3: Busy Bees - Scaling Organizations

Everything becomes micro

We already discovered that the eventual split into dedicated parts for the frontend and backend of an application may be quite useful. Staying on the backend, we've seen the rise of smaller services that need to be orchestrated and joined together: so-called microservices.

From SOA to microservices

While the idea of a service-oriented architecture (SOA) is not new, what microservices brought to the table is freedom of choice. In the early 2000s, the term SOA was introduced to already try that out. However, for SOA, we've seen a broad palette of requirements and constraints. From the communicating protocol, to the discoverability of the API, up to the consuming applications, everything was either predetermined—or at least strongly recommended.

With the ultimate failure of SOA, the community tried to stay away from building too many services too quickly. In the end, it was not only about the constraints imposed by SOA, but also about the orchestration struggle of deploying multiple services with potential interdependencies. How could we go ahead and reliably deploy multiple services into—most likely—two or three environments?

When Docker was introduced, it solved a couple of problems. Most importantly, it brought about a way to reliably get deployments working right. Combined with tools such as Ansible, releasing multiple services seemed feasible and a possible improvement. Consequently, multiple teams around the world started breaking existing boundaries. The common design choices used by these teams would then be taken to form a general architecture style, known as microservices.

When using microservices, there was only a single recommendation: build services that are responsible for one thing. The method of communication (usually REpresentational State Transfer (REST) with JSON) was not determined. Whether services should have their own databases or not was left to the developer. If services should communicate directly or indirectly with each other, this could be decided by the architect. Ultimately, best practices for many situations emerged, cementing the success of microservices even more.

While some purists see microservices as "fine-grained SOA," most people believe in the freedom of choice of using only the single-responsibility principle (SRP). The following figure shows the web applications using microservices with a SPA:

Figure 1.3 – Current state-of-the-art web applications using microservices with a SPA

Figure 1.3 – Current state-of-the-art web applications using microservices with a SPA

With people being busy building backends using microservices, the frontend needed to follow this dynamic approach too. Consequently, a lot of applications are heavily built on top of JavaScript, leveraging SPAs to avoid having to deal with the complexities of having to define both SSR and CSR. This is also shown in Figure 1.3.

Advantages of microservices

Why should a book on micro frontends spend any time looking at the history of microservices or their potential advantages? Well, for one, both start with micro, which could be a coincidence but actually is not. Another reason is that, as we will see, the background and history of both architectures are actually quite analogous. Since microservices are older than micro frontends, they can be used to give us a view into the future, which can only be helpful when making design decisions.

How did microservices become the de facto standard for doing backends these days? Sure—a good monolith is still the right choice for many projects but is not commonly regarded as a "popular choice." Most larger projects immediately head for the microservice route, independent of any evaluations or other constraints they could encounter.

Besides their obvious popularity, microservices also come with some intrinsic advantages, outlined as follows:

  • Failures only directly concern a single service.
  • Multiple teams can work independently.
  • Deployments are smaller.
  • Frameworks and programming languages can be chosen freely.
  • The initial release time is smaller.
  • They have clear architectural boundaries.

Every project willingly choosing microservices hopes to benefit from one or more of the advantages from this list, but there are—of course—some disadvantages too.

Disadvantages of microservices

For every advantage, there is also a disadvantage. What really matters is our perspective and how we weigh the arguments. For instance, if failures only concern a single service, this results in increased complexity for debugging. A service that depends on another service that just failed will also behave strangely. Finding the root cause for why another service failed and working out how to mitigate this situation is increasingly difficult.

Nevertheless, if we go for microservices, we should value their advantages over their disadvantages. If we cannot live with the disadvantages, then we need to either look for a different pattern or try our best to make the disadvantage in question go away as much as possible.

Another example of where an advantage can lead to a disadvantage is in the freedom of choice in terms of frameworks and programming languages. Depending on the number of developers, a certain number of languages may be supported as well. Anything that exceeds that number will be unmaintainable. It's certainly quite fashionable to try new languages and frameworks; however, if no one else is capable of maintaining the new service written in some niche language, we'll have a hard time scaling the development.

Some of the most popular disadvantages are outlined as follows:

  • Increased orchestration complexity
  • Multiple points of failure
  • Debugging and testing gets more difficult
  • Lack of responsibility
  • Eventual inconsistencies between the different services
  • Versioning hell

This list may look intimidating at first, but we need to remember that people already addressed these issues with best practices and enhanced tooling. In the end, it's our call to make the best of the situation and choose wisely.

Micro and frontend

Microservices sound great, so applying their principles to the frontend seems to be an obvious next step. The easiest solution would be to just implement microservices that serve HTML instead of JSON. Problem solved, right? Not so fast…

Just assembling the HTML would not be so difficult, but we need to think bigger than that. We need assets such as JavaScript, CSS, and image files. How can we interleave JavaScript content? If global variables are placed with the same name, which one wins? Should the URLs of all the files resolve to the individual services serving them?

There are more questions than answers here, but one thing is sure: while doing so would be possible in theory, in practice the experience would be limited, and we would lose the separation between backend and frontend, which—as we found out—is fundamental to today's mindset of web development.

Consequently, micro frontends did not exist until quite recently, when some of these barriers could be broken. As we'll see, there are multiple ways to establish a micro frontend solution. As with microservices, there are no fixed constraints. In the end, a project uses micro frontends when independent teams can freely deploy smaller chunks of the frontend without having to update the main application.

Besides some technical reasons, there is also another argument why micro frontends were established later than microservices: they were not required beforehand.

As outlined, the web just recently exploded on frontend code. Beforehand, either separated pages with no uniform user experience were sufficient or a monolith did the job sufficiently well. With applications growing massively in size, micro frontends came to the rescue.

Server-side solutions such as SSI or dedicated logic can help a fair bit to establish a micro frontend solution, but what about bringing this dynamic composition to the client? As it turns out, emerging web standards make this possible too.