Von der Spaghetti über die Lasagne zur Ravioli
In einem interessanten Beitrag über Bare-Metal Monolithen und Serverless Microservices in der AWS-Cloud beschrieb Benoit Hediard, Gründer und CTO von Agorapulse, eine aufschlussreiche und etwas humorvolle Analogie der Entwicklung von Software-Architektur über die Jahrzehnte hinweg mit italienischer Küche. Diese möchte ich hier einleitend gerne erwähnen, um dem Thema rund um sogenannte Micro-Frontends den nötigen Rahmen zu geben.
Stellen Sie sich vor, man könnte die letzten drei Jahrzehnten der Evolution in Sachen Software-Architektur mit drei verschiedene italienische Spezialitäten beschreiben, man käme wahrscheinlich, genau wie Benoit Hediard in seiner Analogie, auf die drei Folgenden:
- 1990er: Die Spaghetti-orientierte Architektur, auch bekannt als Copy&Paste
- 2000er: Die Lasagne-orientierte Architektur, auch bekannt als geschichteter Monolith
- 2010er: Die Ravioli-orientierte Architektur, auch bekannt als Microservice-Verbund
In Aussichten setzt Benoit die nächsten 10 Jahre mit einer weiteren italienischen Speise. In seinem Fall spekuliert er mit einer Pizza. Mir ist zwar noch nicht so klar was er damit meinte, aber ich bin sicher, dass man das Microservice-Prinzip nicht nur im Backend, sondern auch im Frontend einsetzen könnte und sollte. Dies bringt uns zu der Frage, was überhaupt ein Micro-Frontend ist. Hier noch zum Abschluss das originale Bild (Quelle) zur Veranschaulichung.
Nun zurück zum Ravioli-Zeitalter, mittlerweile sollte es jedermann gehört haben: Microservices sind eine tolle Sache! Sie sind schlank, schnell, unabhängig in ihrer eigentlichen Implementation, technologisch zeitgemäss und werden meist in eine Container-Orchestrierung-Software wie Kubernetes, idealerweise durch einen der grossen Cloud-Provider gehosted, platziert. Leider beschränkt sich der Microservice-Trend immer noch zu sehr auf die Backend- & Middleware-Welt, meist steht im Frontend aber weiterhin, bitte entschuldigen Sie mich bereits im Voraus, wenn ich das zu sagen wage, der alt bekannte Monolith.
Wäre es nicht super, wenn auch das Frontend in schlanke, kleine, unabhängige Teile aufgeteilt werden könnte? Oder anders gesagt, wenn im Frontend ähnliche Standards und eine tiefe Grenzschwelle wie in einem Microservice-orientiertes Backend herrschen? Genau dieser Frage gehen wir in unserem heutigen TechUp über Micro-Frontends und deren Nutzen nach.
Was ist denn jetzt genau ein Micro-Frontend
Kurz gesagt, unter einem Micro-Frontend versteht man ein einzelnes, isoliertes Teil einer gesamten Web-Applikation. Diese Micro-Frontends sind dadurch isoliert aufrufbar, beinhalten aber meist keine grundlegenden Standard-Komponenten wie beispielsweise einen Header oder einen Footer, sondern nur die spezifische, fachlich eingegrenzte Funktionalität einer einzelnen Seite.
Dies kann man am besten mit einem Architektur-Diagram wie folgt veranschaulichen. In einer Frontend-Architektur gibt es eine beliebige Vielzahl an Frontend-Modulen, die jeweils beliebig mit dem Framework der Wahl implementiert sein können. Hier sehen wir beispielsweise in Rot ein Angular-Modul welches über ein eigenes CI/CD auf Prod ausgerollt wird. Das Gleiche gilt für React (blau) als zweites und hier noch Vue.js (grün) als drittes Modul. Diese Module werden dann in der Shell als Wrapper, in unserem Veranschaulichungsbeispiel implementiert in Svelte (orange, rechts), zusammengetragen und als Aggregat an den User zur Verfügung gestellt.
Am besten teilt man die Gesamtheit der Applikations-Seitenstruktur in logische, fachlich abgegrenzte Bauteile auf, und definiert in einem zweiten Schritt separate, Domain-spezifische Sub-Applikationen. Diese Sub-Applikationen, die Micro-Frontend-Module, werden dann über ein separates Repository mit einem eigenstätigen CI/CD-Prozess überführt und auch bei Bedarf separat gehosted. So kann jedes Modul einzeln, isoliert weiterentwickelt, gebaut, aufgerufen und idealerweise auch automatisch getestet werden.
Die sogenannte Shell fungiert dabei als Wrapper, welcher alle Micro-Frontend-Module aggregiert und diese dem Kunden als nahtlos benutzbare Web-Applikation vollwertig zur Verfügung stellt. Diesen Prozess des Zusammenführens nennt man in der Fachsprache auch UI Composition.
Ganz wichtig hierbei ist, wie Eingangs bereits erwähnt, spielt es dabei überhaupt keine Rolle, welche Technologien schlussendlich in den einzelnen Micro-Frontends Verwendung finden. Beispielsweise kann der Wrapper ein Angular-Projekt sein, indem ein React, ein VueJs, ein Svelte, sowie ein SvelteKit Projekt eingebunden werden. Der Wrapper, sowohl als auch die eigentlichen Micro-Frontends, müssen hier zwingend kein Framework nutzen; der Wrapper könnte alternativ auch ein E-Commerce-System wie Shopify oder SAP Commerce sein, welches unterschiedliche Micro-Frontends aufruft und in seiner Darstellung dem Nutzer einbettet.
Somit kann man zusammenfassen sagen, dass der Nutzen von Micro-Frontends die gleichen Vorteile wie Microservices im Backend birgt. Die wichtigsten Vorteile dabei wären sicherlich folgende Punkte:
- schlank unterwegs sein
- technologisch unabhängig sein
- keine Altlasten haben
- für einzelne Teile die best möglichste und aktuellste Technologie wählen und einsetzen können
- separate CI/CD & Testing Zyklen einzelner Frontend Teile haben
- Feature oriented Teams, z. B. ein “Product-Team”, welche von A-Z für die Produktdatenbank, die Schnittstellen und für den Produktteil im Frontend zuständig ist und dies weiterentwickelt
Je nach Art des Micro-Frontends unterscheiden sich die Verantwortlichkeiten, teilweise wird das Routing in der Shell oder direkt im Micro-Frontend gemacht. Darum schauen wir uns kurz die gängigsten Implementierungsvariationen einer Micro-Frontend-orientierten Architektur an.
Implementierungsvorschläge einer Micro-Frontend Umgebung
Die einfachste Art – der Hyperlink
Die simpelste aller Lösungen ist der klassische Hyperlink, welcher zu einer komplett anderen Anwendung, beispielsweise auch eine SinglePage-Applikation, zeigt. Der User verliert hier leider seinen Applikationszustand, den State, die Applikation muss dadurch komplett neu geladen werden. Somit kann kein nahtlose und konsistente User Experience gewährleistet werden. Aber auch dies ist eine Art von Micro-Frontend, beispielsweise könnte eine neue Page in ander anderen Technologien wie die vorhandenen Pages implementiert werden.
Ein klassisches, sehr grosses Beispiel hierfür wäre beispielsweise die Google Suite, wobei jede App wie z.B. Gmail als eigenes Micro-Frontend fungiert und diese per Hyperlink verbunden sind.
Die klassische Art – das iFrame
Eine zweite, gängige Möglichkeit, MicroFrontends zu betreiben ist das altbekannte iFrame. Hierüber lässt sich eine andere Website an einer bestimmten Stelle einbinden, es entsteht ein komplett gekapseltes, separates DOM. In der Praxis stösst diese Lösung oft auf suboptimale User Experience. Typischerweise verändert sich das Scrollverhalten auf eine ungewohnte, unintuitive Weise und die erwartete Responsiveness ist zudem meist nicht mehr gegeben ist.
Grundsätzlich hat aber auch dieser, etwas in die Jahre gekommene Ansatz, gewiss ein Einsatzgebiet und seine Daseinsberechtigung. Nur nicht sehr elegant.
Die moderne Art – die Web Component
Die dritte Variante ist sicherlich die optimale und sollte die Art und Weise sein, wie man ein Micro-Frontend einbinden sollte. Dabei wird klar das Ziel verfolgt die HTML-Seiten in wiederverwendbare Komponenten, sogenannte Web Components, aufzuteilen.
Web Components wurde bereits 2012 standardisiert und sind heutzutage virtuell durch jeden Browser unterstützt. Durch das Laden von JavaScript-Dateien bring man dem Browser quasi neue Elemente bei, welche dieser dann rendern kann.
Schaut man sich diese Art genauer an, verstecken sich dahinter drei quintessenzielle Web-Technologien:
- Custom Elements: hiermit können benutzerdefinierte Komponente inkl. Funktionalität definiert, erstellt und genutzt werden, dies ist ein moderner Browserstandard
- Shadow DOM: hiermit ist das DOM der WebComponent gekapselt und wird nicht vom eigentlichen DOM der Page beeinflusst
- HTML-Template: hiermit können Markup Vorlage geschrieben werden, um z. B. Daten dynamisch abzufüllen
Wichtig hier ist, dass der Name der Komponente immer ein Bindestrich enthalten muss. Technisch gesehen gibt es unterschiedliche Frameworks, die Web-Component erstellen können, wir wollen uns heute Angular Elements
genauer anschauen.
Klassisch mit einem Angular-basierten Micro-Frontend
Nun wollen wir uns den Happy-Case mit Angular widmen. Dabei schauen wir wie man mit Angular ein Micro-Frontend bauen könnte.
Zuallererst müssen wir den Angular-Compiler anpassen, dass das Package ngx-build-plus
genutzt wird. Dies erlaubt es uns, die komplette Applikation in ein grosses main
-Bundle zu packen. Die ganze Magic passiert dann im AppModule
, dort wird das custom
-Element erzeugt und definiert. Das sieht wie folgt aus:
|
|
Hier nutzen wir das Package Angular Elements
um unsere SearchResultPageComponent
nach Aussen über den Elementnamen b-nova-homepage-search
freizugeben. Wichtig ist hier, dass nur Angular Komponenten verwendet werden können, die vorher im bootstrap
Teil definiert wurden.
Des Weiteren muss man Angular speziell konfigurieren, dass der Compiler kein Output Hashing
der Dateien macht, um diese immer mit demselben Namen einbinden zu können. Nun können wir in jeder beliebigen Webapplikation das JavaScript einbinden und über unser Custom HTML-Tag das Micro-Frontend einbinden.
|
|
Wie hier zu sehen ist binden wir das CSS und JS in der Shell auch, auch hier gibt es andere Möglichkeiten, dass das Micro Frontend seine benötigten Abhängigkeiten selbst anzieht. In diesem Fall ist der komplette Angular-Context nun im Micro-Frontend drin, auch hier gibt es je nach Anwendungsfall andere Möglichkeiten wie z. B. den Angular Context der Shell zu benutzen.
Selbstverständlich muss man das Micro Frontend nicht separat hosten, sondern kann es beim Build-Prozess der Shell z. B. mit einpacken.
Real World Micro Frontend
Haben Sie es bemerkt? Wir haben bereit ein Micro Frontend im produktiven Einsatz und dies auch schon bei Kunden eingesetzt! 🚀
Auf unserer Homepage haben wir die Funktionalität der Suche ausgelagert in ein Angular Micro Frontend. Der Header, die Navigation und der Footer kommen von unserem Magnolia CMS, die eigentliche Funktionalität der Page kommt von unserem Micro Frontend. Wir behaupten an dieser Stelle mal, dass man den Einsatz eines Micro Frontends als Benutzer nicht merkt, spürt oder sieht, da die UX, das Scroll-Verhalten usw. identisch zu einer normalen Webapp ist.
Diese Aufteilung erlaubt es uns zusätzlich, kleine Teile einer bestehende Webanwendung mit neueren Technologien umsetzen ohne gleich das ganze Projekt migrieren zu müssen. So werden wir wahrscheinlich das nächste Micro-Frontend mit Svelte o. ä. umsetzen.
Wieso genau auf Micro Frontends setzen?
Ein riesiger Vorteil der Ravioli-Architektur im Frontend ist die Nachhaltigkeit und die Möglichkeit, technologisch unabhängig für Weiterentwicklungen und Neuentwicklungen zu sein. Stellen Sie sich vor, sie nutzen aktuell ein CMS System und wollen eine kleine Komponente darin modernisieren. Der Einsatz eines modernen Frontend Frameworks würde sich anbieten. Ohne Web Components oder generell Micro Frontends müssten Sie das ganze Projekt migrieren oder mühsam ein Framework ‘reinbasteln’.
Mit dem Einsatz von Micro Frontends können die punktuell bestehende Applikationen anpassen, erweitern oder modernisieren. Auch beim Starten eines neuen Projektes empfiehlt sich dieser Ansatz, da sie für jeden Anwendungsfall das passende Produkt oder Framework evaluieren und nutzen können.
Ausserdem ist es eine unglaublich schlanke und coole Sache, auch im Frontend ‘Feature oriented’ zu arbeiten, einen schlanken CI / CD Prozess mit automatisieren Tests zu haben und weg vom Monolith zu gehen.
Sie brauchen Unterstützung bei Ihrer Webanwendung oder wollen ein neues Projekt mit zukunftssicheren Tools starten?
Kontaktieren Sie uns, wir helfen Ihnen gerne!