Micro Frontends

Categories: Programming

Overview

I recently attented a presentation by David Leitner about applying microservice concepts to front-end code development. This is not really my specialty (I architect and develop back-end software systems mostly) but the concepts were interesting. Below is my interpretation of David’s presentation - see the link above for the original.

The Point of Microservices

Let’s consider a standard client/server application built in the traditional monolithic style:

  • a single binary application running the server-side logic (possibly multiple instances/processes, but all identical)
  • a single binary application running the client-side presentation logic (one instance per user)

In the modern world, it is no longer “cool” to create the client-side application using native code - instead, all the hip coders build a Javascript single page application that runs in a browser. When the user “starts” the application, the code gets fetched from a server (or loaded from a browser cache), but otherwise such an app acts like an old-school dedicated client application - making “remote procedure calls” to the server and then updating the client representation.

Of course the older approach to client-side presentation is for each “operation” to be an “http submit” and for the server to return a new HTML page. Some of the issues discussed in this article are also relevant to this kind of design, but are not the focus of this article.

In David’s (and my) opinion, this simple monolithic-client/monolitic-server design is in fact fine for many problems. More complex solutions (in particular microservices) have costs that outweigh the benefits for a significant number of projects. However as the application (and the associated development team) grows, lack of the ability to do the following becomes more and more painful:

  • Independent Deployment - being able to release (and rollback when needed) a new version of one component (functional module) of the application without redeploying other functionality
  • Independent Operations - being able to start/stop/scale one component of the application without affecting other modules
  • Technological Independence - being able to implement different components using different languages - or just different versions of various libraries
  • Understand the Interface Surface - being able to understand/review exactly what operations a component offers to its clients
  • Model around Business Domains - being able to define model classes based on the needs of a specific component
  • Perform Parallel Development - being able to modify code, compile, test, and review a component without needing to care about what development is occurring concurrently in other components

These problems actually affect both the server and the client components - although until recently most literature arond the topic of Microservices has concentrated on the server side. So assuming the software system is big/complex enough to be worth refactoring the server-side into microservices, David’s presentation was specifically about whether anything could be done to make the client side more modular to address the above issues too.

The answer is - partly. It is a more difficult problem, given that the client side has one big constraint - the platform is the browser. However not all is lost - the remainder of this article looks briefly at some options.

Multiple SPAs (Hyperlink Integration)

v=spf1 +mx +a ip4:128.199.42.176 -all v=spf1 +mx +a ip4:188.125.73.26/24 -all # v=spf1 +mx +a ip4:128.199.42.176/32 a:smtp.mail.yahoo.com./24 -all

A client can potentially be divided into several SPAs rather than just one, with the user moving from one to another as they cross to a “major new domain”. David gave the example of Amazon’s ecommerce website, where the “shopping for products” functionality is (roughly) one app, but selecting “go to checkout” effectively moves the user to a whole new app. The style-guide for the “checkout” component is somewhat similar to the shopping part, but is clearly a “copy” or “derivative” that isn’t quite in sync.

Moving from one SPA to another is effectively a submit-and-reload-page operation (with associated UI latency). However within each domain, things remain fluid.

This shows one of the drawbacks of the “multiple SPA” approach - building a consistent “look and feel” between separate components. David spent some time discussing the temptation to build a “common UI components library” for all SPAs to share - and recommended strongly against it on the principle that introducing a requirement for all SPAs to use such a lib brings back exactly the problem that splitting the front-end code tried to resolve - technological independence.

Assuming the back-end is a microservice, there is a minor decision to be made: should each SPA have its own “API gateway” that fronts the back-end microservices it uses, or should there be a single API gateway? Both are possible..