Micro Frontends Teil 2 – Ansätze zur Komposition von User interfaces

Montag, 14.3.2022

Nachdem wir im ersten Teil der Serie zum Thema Micro Frontends die Grundlagen geschaffen haben, wenden wir uns im zweiten Teil der praktischeren Seite der Architekturform zu. Genauer gesagt behandelt der Blogbeitrag verschiedene Ansätze, User Interfaces zusammenzuführen, die von unterschiedlichen Teams bereitgestellt werden:

image2021-4-9_13-41-50

Abbildung 1: Integration von Pages und Fragments in einem UI.

 

Abb. 1 illustriert die wichtigsten Komponenten im Zusammenhang mit Micro Frontends und deren Beziehung zueinander. Hauptsächlich wird unterschieden zwischen

  • Fragment: Ein Fragment ist ein abgeschlossenes UI-Element.

und

  • Page: Eine Page kann eigene UI-Elemente besitzen und darüber hinaus von anderen Teams bereitgestellte Fragmente integrieren.

Durch technische Maßnahmen der Frontend-Integration ergibt sich somit eine Gesamtanwendung, die aus Pages und einer beliebigen Anzahl extern zugeführter Fragmente besteht.

Der User bekommt von der Magie im Hintergrund nichts mit, sondern erfährt die Applikation als eine in sich schlüssige und kohärente Anwendung.

 

Welche Integrationsansätze stehen zur Auswahl?

Bei der Auswahl eines Integrationsansatzes wird zwischen Build-Time-Integration und Runtime-Integration unterschieden.

Build-Time Integration

Wie der Name bereits erklärt, werden Pages und Fragmente bei der Build-Time Integration zur Buildzeit zusammengeführt. Eine der meist genutzten Anwendungsformen stellt dabei die Einbindung von UI-Dependencies über z.B. npm-Packages dar. Nach ihrer Einbindung können sie bspw. als Custom Elements in den Quellcode integriert werden. Der große Nachteil von Build-Time Integration liegt jedoch darin begründet, dass bei Änderungen der Fragmente oder Pages immer wieder erneut die aktuellste Version eingebunden, gebuildet und deployt werden muss. Dies widerspricht dem Ziel, dass Teams in einer Micro-Frontends-Organisation agil und möglichst unabhängig voneinander arbeiten können. Aus diesem Grund zählen die Integrationsansätze der Runtime Integration meist zu den beliebteren. Auf diesen liegt dementsprechend der Fokus in dem Blogbeitrag.

Runtime Integration

Auch hier verrät der Name bereits das entscheidende Merkmal der Integrationsmethode. Fragmente und Pages werden dynamisch zur Laufzeit der Anwendung integriert. Die Einbindung erfolgt bei einem Großteil der Kompositionsansätze über die Referenzierung einer URL, unter der beispielweise ein Fragment bereitgestellt wird. Folgende Ansätze werden bei der Runtime Integration unterschieden:

  • Komposition via Links
  • Komposition via iframes
  • Komposition via Ajax
  • Serverseitige Komposition via Server Side Includes (SSI)
  • Clientseitige Komposition via Web Components
  • Cherry Picking mit Universal Rendering

 

1. Komposition via Links

Beschreibung

Jedes Team konzipiert seine Pages in HTML/CSS/JS. Hier wird bewusst nur von Pages gesprochen, da über Links lediglich auf andere Pages verwiesen werden kann. Die Integration eines Fragmente innerhalb einer Seite ist mit Links nicht möglich. Als Kontrakt zwischen den Teams werden URLs genutzt. Möchte ein Team, das eine Page erstellt, eine andere Page einbinden bzw. auf diese verweisen, so referenziert es per Anchor-Tag die Quelle dieser Page. Diese Form der Komposition ist die bei weitem einfachste und rudimentärste.

Vorteile

  • Geringere Kopplung: Durch das Nutzen von Links, kann die Anwendung separiert voneinander aufgebaut werden und die Kopplung reduziert sich.
  • Hohe Robustheit: Fällt ein Micro Frontend aus, so stürzt nicht die ganze Anwendung ab, sondern der Link, hinter dem sich der ausgefallene Teil der Anwendung befindet, funktioniert nicht.

Herausforderungen

  • Verwaltung der URL-Schemata: Wächst die Applikation, können sich auch URL-Schemata ändern, die die anderen Teams immer wieder anpassen müssen. Aus diesem Grund macht eine zentrale Verwaltung über beispielsweise eine JSON-Datei Sinn, in der Key-Value-Pairs hinterlegt sind. Ändert sich eine URL, so müssen die Teams ihre Referenzen nicht anpassen, da der Key gleich bleibt.
  • Informationen anderer Teams „verstecken“ sich hinter den Links: Da eine Integration über Fragmente nicht möglich ist, bekommt der User die Informationen erst präsentiert, wenn er auf den Link klickt.
  • Technische Redundanz und Overhead: Beinhaltet die Anwendung Header, Footer oder weitere omnipräsente Elemente, müssen diese auf jeder Page von jedem Team integriert werden.

Beispiel

Die hier vorgestellte Beispielanwendung stammt ursprünglich von Michael Geers und wurde für diesen Blogartikel leicht abgeändert. Die folgende Abbildung zeigt das simple UI:

Abbildung 2: UI der begleitenden Beispielanwendung.

Page – team-decide/product/pullover.html:

Page – team-inspire/recommendations/pullover.html:

 

2. Komposition via iframes

Beschreibung

Bei diesem Integrationsansatz gelten dieselben Voraussetzungen wie bei der Komposition via Links mit dem einzigen Unterschied, dass anstelle von Anchor-Tags iframes benutzt werden und somit auch die Integration von Fragmenten innerhalb von Pages ermöglicht wird. Als Kontrakt zwischen den Teams wird dementsprechend lediglich die URL definiert.

Vorteile

  • Gleichbleibende lose Kopplung und Robustheit: Mit Hilfe von iframes erhält man die Möglichkeit, Fragments auch innerhalb von Pages einzubinden, ohne dabei die Kopplung zu erhöhen oder Robustheit einzubüßen.
  • Starke Isolation: iframes gewährleisten eine starke Isolation. Das bedeutet, dass Skripte und Styles des iframes keinen Einfluss auf die Page und umgekehrt die Skripte und Styles der Page keinen Einfluss auf die Inhalte des iframes haben. Außerdem bringen iframes diverse Security Features mit.
  • Reduzierter Overhead: Redundante UI-Komponenten (z.B. Header, Footer, …) können durch iframes ersetzt werden, sodass die Implementierung lediglich einmal stattfindet und nur auf diese referenziert werden muss.

Herausforderungen

  • Höhendefinition des iframes: Ein großer Nachteil von iframes ist, dass die genaue Höhe des Inhalts bekannt sein muss, um das iframe entsprechend auf einer Page platzieren zu können. Dies stellt bei statischen Seiten kein Problem dar, wird allerdings bei dynamischen/responsiven Inhalten schwierig bis unmöglich. Abhilfe können JavaScript-Bibliotheken wie z.B. iframe-resizer schaffen.
  • Performance-Overhead: Jedes iframe kreiert einen eigenen neuen Browsing-Context, der zu mehr Speicher- und CPU-Auslastung führt. Gerade auf großen Pages mit vielen integrierten iframes sind Performance-Einbußen spürbar.
  • Schlechte Accessibility und Nachteile für SEO: iframes durchbrechen die semantische Struktur einer HTML-Seite, sodass Screen Reader mehrere Dokumente mit eigenem Titel, Informationshierarchie und Navigationszustand sehen. Außerdem würde ein Search-Engine-Crawler eine Seite mit einem iframe nicht als eine, sondern als zwei Seiten indexieren.

Beispiel

Page - team-decide/product/pullover.html:

Fragment – team-inspire/recommendations/pullover.html:

 

3. Komposition via Ajax

Beschreibung

Auch bei diesem Integrationsansatz stellt jedes Team seine Pages bzw. Fragmente in Form von HTML/CSS/JS bereit. Der Kontrakt zwischen den Teams besteht aus der URL und zuzüglich aus Namespace-Konventionen für CSS und JS, da eine Isolation wie bei der Komposition via Links und iframes nicht gegeben ist. Mit Hilfe eines Ajax-Calls ist eine tiefere Integration in die Seitensemantik möglich, da der entsprechende HTML-Code direkt ins DOM integriert wird.

Vorteile

  • Progressive Enhancement: Falls der Ajax Call fehlschlägt, können Fallbacks als Anchor-Tag oder statischer HTML-Code definiert werden.
  • Barrierefreiheit für Screen Reader und Search Engines: Da die Seitensemantik einheitlich strukturiert ist und nicht durchbrochen wird, treten keine Problem wie bei der Komposition via Links oder iframes auf.
  • Keine Layout-Problematik: Durch die Integration des HTML-Codes direkt ins DOM gibt es keine Höhenprobleme, wie bei iframes der Fall.

Herausforderungen

  • Konflikte bezüglich Styles und Skripten: Es muss eine Namespace-Konvention (z.B. Block, Element, Modifier) zwischen den Teams herrschen, da es ansonsten zu Kollisionen von CSS oder globalen JavaScript-Variablen kommen kann.
  • Asynchrones Laden der Inhalte: Das asynchrone Laden verursacht meist kleine Verzögerungen bis die Inhalte angezeigt werden, je nach dem wie groß das zu ladende Fragment ist. Dies ist gerade für Inhalte im Viewport problematisch.
  • Es gibt keinen Lifecycle für Skriptcode: Implementiert das geladene Fragment einen Event Listener, benötigt es einen Mechanismus, um darüber informiert zu werden, wann die Page geschlossen wurde und die Event Listener wieder entfernt werden können.

Beispiel

Page – team-decide/product/pullover.html:

Ajax-Call - team-decide/static/page.js:

Fragment – team-inspire/recommendations/pullover.html:

 

4. Serverseitige Komposition via SSI

Beschreibung

Wie bei den vorherigen Ansätzen stellen die Teams Pages und Fragmente in HTML/CSS/JS bereit und nutzen als Kontrakt für die Integration URLs. In diesem Fall werden relative URLs anstatt absoluter URLs verwendet, da die Kommunikation über einen Frontend-Proxy (z.B. NGINX, Varnish) läuft, der das Markup serverseitig zusammenbaut und dem Browser zur Verfügung stellt. Die Integration von Fragmente in Pages funktioniert bei diesem Ansatz über sogenannte SSI-Direktiven, die die entsprechende relative URL beinhalten. Stößt der Frontend-Proxy auf eine SSI-Direktive, fragt er über die mitgelieferte URL das benötigte Fragment an und integriert es in das DOM der Page.

Vorteile

  • Serverseitiger Zusammenbau: Das Markup der Page ist bereits komplett zusammengestellt, wenn es beim Browser ankommt. Dieser muss die Seite lediglich anzeigen ohne JavaScript auszuführen.
  • First-Page Load Speed, Robustheit und Progressive Enhancement: Der Browser zeigt die Page direkt an. Außerdem ist auch dieser Ansatz sehr robust gegen Ausfälle einzelner Bereiche der Anwendung und unterstützt Progressive Enhancement.
  • Stabilität der SSI-Direktive: Die Direktive wurde bereits 1990 eingeführt und weist somit eine hohe Stabilität wie Kompatibilität auf.
  • Entlastung der Nutzergeräte: Dadurch, dass die Page bereits voll zusammenbaut im Browser ankommt, wird wenig Leistung auf Seiten der Nutzergeräte benötigt, um die Anwendung zu nutzen.
  • SEO-freundlich: Serverseitig generiertes Markup ist gut geeignet für Search Engines, da es eine reine Seitensemantik aufweist.

Herausforderungen

  • Ladezeiten: Die gesamte Page lädt lediglich so schnell wie das am längsten ladende Fragment benötigt. Diese Ladezeit hat Auswirkungen auf die Time To First Byte (TTFB), also die Zeit, die vergeht, bis das erste Datenpaket beim Browser ankommt.
  • Generelle Abhängigkeit der Page von den Fragmente: Kann ein Fragment nicht geladen werden, wird die Seite nicht angezeigt. Dieses Problem kann durch Timeouts und Fallbacks gelöst werden, soweit diese auch vom Frontend-Proxy unterstützt werden.
  • Namespacing: Auch bei diesem Integrationsansatz muss darauf geachtet werden, dass keine Kollisionen von CSS oder JavaScript-Code entstehen.
  • Interaktivität: Aufgrund des serverseitigen Zusammenbaus ist diese Methode nicht besonders gut für Anwendungen geeignet, die viel Interaktion bieten sollen.

Beispiel

NGINX-Konfiguration – webserver/nginx.conf:

Page – team-decide/product/pullover.html:

Fragment – team-inspire/fragment/recommendations/pullover.html:

 

5. Clientseitige Komposition via Web Components

Beschreibung

Bei diesem Ansatz werden Pages und Fragmente vorrangig als Web Components integriert. Die Kontrakte zwischen den Teams bestehen wie gehabt aus URL und zusätzlich aus dem Tag-Namen des Custom Elements, welches verwendet werden soll. Der Einsatz von Custom Elements ermöglicht eine einfache und unkomplizierte deklarative Nutzung. Werden unterschiedliche Frameworks (React, Vue, Angular) benutzt, bieten diese Wrapper an, um das Markup als Custom Element bereitzustellen.

Vorteile

  • Nutzung eines einheitlichen Standards: Durch die Standardisierung von Web Components können Brüche innerhalb der API vermieden werden. Diese bleibt langfristig stabil.
  • Integration verschiedener Frameworks: Da es sich bei Web Components um einen einheitlichen Standard handelt, existieren für einige Frameworks bereits Wrapper, um Komponenten in ein Custom Element umzuwandeln.
  • Isolation von Styling: Mit Hilfe der ShadowDOM-API können Stylings effizient isoliert werden, sodass sie keine Auswirkungen nach außen haben, aber auch keine Beeinflussung von außen auf das Styling des Custom Elements möglich ist.

Herausforderungen

  • Es wird clientseitiges JavaScript benötigt: Das Einbinden von Web Components erfolgt mit JavaScript, so dass die einzelnen Komponenten in JavaScript definiert und implementiert werden müssen. 
  • Fehlende Unterstützung älterer Browser: Die Unterstützung des Web Component Standards ist teilweise noch nicht in allen Browsern verfügbar. Gerade neue Features werden noch nicht vollständig unterstützt.
  • Implementierungsgeschwindigkeit ist langsamer: Durch die Verwendung von weniger mächtigen APIs anstatt vollständiger Frameworks, benötigt die Entwicklung mehr Zeit, um Funktionen umzusetzen. Viele Funktion, welche man vorher durch das Framework geschenkt bekommen hat, müssen jetzt selbst umgesetzt werden.

Beispiel

Page – team-decide/product/pullover.html:

Fragment – team-inspire/static/fragment.js:

 

6. Cherry Picking mit Universal Rendering – Eine Kombination aus serverseitiger - und clientseitiger Integration

Beschreibung

Im Großen und Ganzen kann zwischen server- und clientseitiger Komposition unterschieden werden. Hierbei steht bei serverseitiger Komposition insbesondere der Vorteil des hohen First Page Load Speed im Vordergrund. Nachteilig ist hingegen die verminderte Interaktivität der Anwendung zu sehen. Clientseitige Komposition bietet genau entgegengesetzte Eigenschaften, sodass eine Kombination dieser beiden Kompositionsformen einen durchaus nützlichen Mehrwert bietet und gleichzeitig zu mehr Robustheit führt. Dieser Ansatz wird als Universal Rendering bezeichnet. Kurzum ist es möglich, Markup sowohl server- als auch clientseitig zu rendern oder upzudaten. Als Kontrakt zwischen den Teams dient für den serverseitigen Teil die relative URL sowie für den clientseitigen Teil der Tag-Name des Custom Elements.

Vorteile

  • Kombination der Vorteile aus client- sowie serverseitiger Komposition/Rendering: Schneller First Page Load Speed sowie schnelle Reaktion auf Nutzerinteraktionen.

Herausforderungen

  • Erhöhte Komplexität: Das Aufsetzen, Betreiben und Debuggen einer Anwendung, die Universal Rendering nutzt, ist komplizierter und aufwändiger als lediglich eine reine client- oder serverseitige Lösung aufzubauen.

Beispiel

NGINX-Konfiguration – webserver/nginx.conf:

Page – team-decide/product/pullover.html:

Fragment – team-checkout/static/fragment.js:

Fragment – team-inspire/fragment/recommendations/pullover.html:

 

Fazit

Folgende Abbildung zeigt die Stärken und Schwächen der einzelnen Integrationsansätze:

 

Abbildung 3: Vergleich der verschiedenen Integrationsansätze.

Wie so oft liegt es am vorliegenden Einsatzszenario und den Anforderungen der Anwendung, die erstellt werden soll, welcher Integrationsansatz gewählt wird. Aus der Abbildung lässt sich gut ablesen, welchen Einsatzzweck eine Kompositionsmethode gut oder weniger gut abdeckt. Wird beispielsweise ein internes Dashboard entwickelt, das lediglich präsentierenden Charakter aufweist, wenig Interaktion verlangt und statische Inhalte darstellt, eignet sich die Komposition via iframes sehr gut, da es sehr simpel umzusetzen ist. Für interne Tools spielen Kriterien wie Ladegeschwindigkeit, Accessibility und SEO keine große Rolle, weshalb diese vernachlässigt werden können.

Eine Vertiefung in das Thema wird Dr. Lofi Dewanto in seinem Vortrag auf dem NAVIGATE Kongress geben. Melden Sie sich jetzt kostenlos hier an.


Sie möchten sich mit uns zu dem Thema Microfrontends austauschen? Gerne stellen wir Ihnen auch weiteres Material zum Thema zur Verfügung. Kommentieren Sie einfach unter diesem Beitrag oder kontaktieren uns per Mail.


Dieser Blogbeitrag ist in einem studentischen Projekt in Zusammenarbeit mit der Fachhochschule Münster entstanden. 
Du interessierst dich für ein Praktikum, Werksstudententätigkeit oder eine Abschlussarbeit bei uns? Dann schau hier rein und erfahre mehr über die Tätigkeit bei der viadee und entdecke unsere Themen für Abschlussarbeiten. 


zurück zur Blogübersicht

Diese Beiträge könnten Sie ebenfalls interessieren

Keinen Beitrag verpassen – viadee Blog abonnieren

Jetzt Blog abonnieren!

Kommentare

Kevin Haase

Kevin Haase

Kevin Haase unterstützt als IT-Consultant und IT-Architekt Unternehmen bei der Umsetzung von individuellen Lösungen und hat langjährige Erfahrung in der Entwicklung mit verschiedenen Javascript Frameworks gesammelt.