A software architect's approach towards using Angular (and SPAs in general) for microservices aka microfrontends

People ask me on regular basis how to use SPAs and/or Angular in an microservice-based environment. The need for such microfrontends is no surprise, as microservices are quite popular nowadays. The underlying idea of microservices is quite simple: Create several tiny applications -- so called microservices -- instead of one big monolytic applications. This leads for instance (but not only) to smaller teams (per microservice) that can make decisions faster and chose for the "best" technology that suites their needs.

But when we want to use several microservices that form a bigger software system in the browser, we need a way to load them side by side and to isolate them from each other so that they cannot interact in an unplanned manner. The fact that each team can use different frameworks in different versions brings additional complexity into play.

Fortunately, there are several approaches for this. Unfortunately, no approach is perfect -- each of them has it's own pros and cons.

To decide for one, a software architect would evaluate those so called architectural candidates against the architectural goals given for the software system in question. Typical (but not the only) goals for SPAs in microservice-based environments are shown in the next section.

Architectural Goals

Architectural Goal Description
a) Isolation Can the clients influence each other in an unplanned way?
b) Separate Deployment Can the microservices be deployed separately without the need to coordinate with other teams responsible for other microservices?
c) Single Page Shell Is the shell, composing the loaded microfrontends a SPA -- or does it at least feel like one for the user (no postbacks, deep linking, holding state)
d) Different SPA-Frameworks Can we use different SPA frameworks (or libraries) in different versions
e) Tree Shaking Can we make use of tree shaking?
f) Vendor Bundles Can we reuse already loaded vendor bundles or do we need to load the same framework several times, if it's used by several microfrontends
g) Several microfrontends at the same time Can we display several microfrontends at the same time, e. g. a product list and a shopping basket
h) Prevents version conflicts Does the approach prevent version conflicts between used libraries?
i) Separate development Can separate teams develop their microfrontends independently of other ones

Evaluation

The following table evaluates some architectural candidates for microfrontends against the discussed goals (a - g).

Architectural Candidate a b c d e f g h i
I) Just using Hyperlinks x x x x x x
II) Using iframes x x x x x x x x
III) Loading different SPAs into the same page x x x x x x
IV) Plugins x x x
V) Packages (npm, etc.) x x x x
VI) Monorepo Approach x x x x x
VII) Web Components x x x x x x

If you are interested into some of those candidates, the next table provides some additional thoughts on them:

Nr Remarks
I) Just using Hyperlinks We could save the state before navigating to another microfrontend. Using something like Redux (@ngrx/store) could come in handy b/c it manages the state centrally)
II) Using iframes We need something like a meta router that synchronizes the url with the iframes ones
III) Loading different SPAs into the same page A popular framework that loads several SPAs into the browser is Single SPA. The main drawback seems to be the lack of isolation, cause all applications share the same global namespace and the same global browser objects. If the latter ones are monkey patched by a framework (like zone.js) this affects all the loaded SPAs
IV) Plugins Dynamically loading parts of a SPA can be done with Angular but webpack and so the CLI demands on compiling everything together. Switching to SystemJS would allow to load parts that have been compiled separately
V) Packages This means, providing each frontend as a package via (a private) npm registry or the monorepo approach and consuming it in a shell application. This also means, that there is one compilation step that goes through each frontend.
VI) Monorepo Approach This approach, heavily used at Google or Facebook, is similar to using packages but instead of distributing code via a npm registry everything is put into one source code repository. In addition, all projects in the repository share the same dependencies. Hence, there are no version conflicts b/c everyone has to use the same/ the latest version. And you don't need to deal with a registry when you just want to use your own libraries. A good post motivating this can be found here. To get started with this idea in the world of Angular, you should have a look at Nrwl's Nx - a carefully thought through library and code generator that helps (not only) with monorepos.
VII) Web Components This is similar to III) but Web Components seem to be a good fit here, b/c they can be used with any framework - at least, in theory. They also provide a bit of isolation when it comes to rendering and CSS due to the usage of Shadow DOM (not supported by IE 11). Currently, the Angular Team is working on a very promising Labs project called Angular Elements. The idea is to compile Angular Components down to Web Components.

The result of this evaluation shows that the iframe approach is quite tempting even though using this word causes shivering for most web devs. That's why I've decided to create a small library providing a meta router that loads different SPAs into iframes. This router also takes care about creating iframes so that we don't need to touch them manually.

But to make it clear: There is no perfect solution and it really depends on your current situation and upon how important the architectural goals are for you. E. g. I've seen many team writing successful applications leveraging libraries and at companies like Google and Facebook there is a long tradition of using monorepos. Also, I expect that Web Components will be used more and more due to the growing framework and browser support.

It's not an "either/or thing"!

Mixing those approaches can also be a good idea. For instance, you could go with Hyperlinks or iframes for the general routing and when you have to display widgets from one microfrontend within an other one, you could choose for libraries or web components.

 

 
Sie wollen mehr zum Thema A software architect's approach towards using Angular (and SPAs in general) for microservices aka microfrontends wissen? Hier können Sie eine Anfrage für eine unverbindliche Schulung ode Beratung bzw. einen Workshop erstellen.
 
Unverbindliche Anfrage
 
 

Schulung und Beratung

Angular: Strukturierte Einführung

In dieser Schulung erfahren Sie von bekannten Insidern und Angular Experten der ersten Stunde anhand eines durchgängigen Beispiels, welche Konzepte hinter dem modernen Single-Page-Application-Framework aus der Feder von Google stecken und lernen diese für Ihre eigenen Projekte zu nutzen. Zusätzlich werden sie selbst eine erste Angular-Anwendung zu schreiben. Diese orientiert sich an Best Practices und kann somit als Vorlage für eigene Projekte herangezogen werden. Zum Einsatz kommt die jeweils neueste Version von Angular.

Details

Advanced Angular: Architekturen für Enterprise-Anwendungen

In dieser weiterführenden Intensiv-Schulung lernen Sie von namhaften Insidern, wie sich große und skalierbare Geschäftsanwendungen mit Angular entwickeln lassen. Mehrere Architekturansätze und Best Practices werden anhand einer Fallstudie aufgezeigt und diskutiert. Die Fallstudie wird in den einzelnen Übungseinheiten erweitert und kann als Vorlage für eigene Vorhaben dienen.

Details

Weitere Schulungen ...