Micro-Frontends mit Web Components

Micro-Frontends sind Benutzeroberflächen, die sich aus kleinen isolierten Anwendungen zusammensetzen. Implementieren kann man sie zum Beispiel mit Web Components.

Lesezeit: 7 Min.
In Pocket speichern
vorlesen Druckansicht Kommentare lesen
Von
  • Christian Liebel

Micro-Frontends sind Benutzeroberflächen, die sich aus kleinen isolierten Anwendungen zusammensetzen. Implementieren kann man sie zum Beispiel mit Web Components.

Es handelt sich um die Übertragung des Microservice-Konzepts aus dem Backendbereich auf das Frontend: Größere Anwendungen werden in kleinere, besser zu implementierende und zu wartende Unteranwendungen zerlegt. Entwickler können dabei die Sprachen und Frameworks wählen, die zu ihnen und dem konkreten Anwendungsfall passen. Web Components sind ein möglicher Ansatz zur Implementierung solcher Micro-Frontends.

Es gibt viele Möglichkeiten, Micro-Frontends zu bauen: Unter anderem können Inline Frames (IFrames) eingesetzt werden, in denen unterschiedliche Single-Page-Apps ausgeführt werden. Über jeweils zu implementierende Kommunikationsschichten können diese miteinander Daten austauschen. Die Module Federation in Webpack 5 erlaubt das Nachladen von fremdem Programmcode zur Laufzeit, um dasselbe Ziel zu erreichen – hier nicht in unterschiedlichen Frames, sondern in ein und demselben Browsingkontext. Ganz ähnlich verhält es sich mit Web Components, mit denen sich dieser Artikel beschäftigt.

Web Components sind das eingebaute Komponentenmodell des Web. Entwickler können dabei eigene HTML-Elemente definieren und deren Aussehen sowie Verhalten selbst steuern. Die Technologie ist noch verhältnismäßig neu, funktioniert aber in den vier Evergreen-Browsern Chrome, Edge, Firefox und Safari seit längerem.

Der Datenaustausch erfolgt über benutzerdefinierte DOM-Attribute bzw. -Eigenschaften sowie -Ereignisse, auf der Komponente können auch eigene JavaScript-Methoden definiert werden, das Theming der Komponenten ist dabei über CSS Custom Properties möglich.

Web Components lassen sich mit Plain JavaScript schreiben, es gibt jedoch auch Bibliotheken wie Lit, die das Verfassen solcher Elemente noch einmal deutlich vereinfachen. Weiterhin erlauben auch Frameworks wie Angular (Angular Elements) oder Stencil das Verfassen eigener Web Components. Entwickler können hier einfach einen passenden Unterbau aussuchen, die Komponenten lassen sich anschließend problemlos miteinander kombinieren.

Web Components werden zur Laufzeit durch den Verwender registriert, damit ist auch ein Nachladen beliebiger Komponenten während der Ausführung möglich. Es gilt jedoch zu bedenken , dass der hierfür erforderliche JavaScript-Code innerhalb des eigenen JS-Kontextes ausgeführt wird. Einmal geladen kann der fremde Code etwa den Local Storage oder auch Cookies auslesen, wenn sie für JavaScript sichtbar sind. Wenn dies vermieden werden soll, bieten sich die oben genannten IFrame-Ansätze an.

Vor wenigen Monaten habe ich hier auf dem ÜberKreuz-Blog meinen webbasierten Remake von Microsoft Paint vorgestellt. Es handelt sich dabei um eine Progressive Web App, die komplett alleinstehend betrieben werden kann. Die Anwendung ist zugleich jedoch eine Web Component und kann somit auch in beliebige andere Anwendungen eingebettet werden. Die Paint-Web-Component steht unter dem Paket @christianliebel/paint auf npmjs.org zur Verfügung.

Die Paint-Web-Component schreibt den Dateinamen des Dokuments in einen Adobe-Spectrum-Button

Viele Softwarehersteller setzen Design Systems ein, die Steuerelemente in der eigenen Corporate Identity enthalten. Adobe hat sein Design System namens Spectrum mit Web Components realisiert und quelloffen zur Verfügung gestellt. Unter anderem kommen diese Komponenten beim jüngst eingeführten Photoshop Web zum Einsatz. Zur einfachen Demonstration des Ansatzes wird der Titel des aktuell bearbeiteten Dokuments der Paint-App auf einen Spectrum-Button geschrieben:

<html>
<body>
<paint-app style="width: 600px; height: 480px;"></paint-app>
<sp-theme scale="large" color="dark"><sp-button></sp-button></sp-theme>
<script
src="https://unpkg.com/@christianliebel/paint/dist/elements/index.js"
type="module"></script>
<script
src="https://jspm.dev/@spectrum-web-components/bundle/elements.js"
type="module"></script>
<script>
const paintApp = document.querySelector('paint-app');
const button = document.querySelector('sp-button');
paintApp.addEventListener('titlechange',
evt => button.innerText = evt.detail.title);
</script>

Um zu wissen, welche benutzerdefinierten HTML-Elemente von Drittanbieterpaketen zur Verfügung gestellt werden, gibt es das sogenannte Custom Element Manifest. Es zählt alle Web Components mit den verfügbaren Attributen, Eigenschaften, Ereignissen und CSS-Variablen auf. Für manche Umgebungen gibt es auch Generatoren, um die Manifest-Datei automatisiert erstellen zu lassen.

{
"version": 2,
"tags": [
{
"name": "paint-app",
"description": "An open-source, Web Components-based remake" +
"of MS Paint using modern web capabilities.",
"properties": [],
"events": [
{
"name": "titlechange",
"description": "The titlechange event fires whenever" +
"the document's title changes, for example, " +
"when a document is saved with a new name," +
"or a document was opened from the file system.",
"type": "{ title: string }"
}
],
"slots": [],
"cssProperties": []
}
]
}

Bei Micro-Frontends ergibt sich das Problem, dass eigentlich unabhängige Anwendungen integriert werden müssen. Eventuell gibt es Versionsabhängigkeiten zwischen den Einzelanwendungen, die erfüllt werden müssen. Ist das nicht möglich, funktioniert auch die Gesamtanwendung nicht. Komponentenmarktplätze wie npmjs.org haben sich dieser Problematik durch das Konzept der semantischen Versionierung genähert. Hier ergibt sich durch die Versionsnummer, ob bei einem Update Breaking Changes zu erwarten sind. Ein weiterer Ansatz besteht darin, Schnittstellen dauerhaft abwärtskompatibel zu gestalten. Die Win32-API oder die Web-Plattform sind gute Beispiele hierfür, allerdings bedarf es hierfür passender organisatorischen Strukturen, um dieses Ziel einzuhalten.

Speziell auf Web Components bezogen lassen sich Custom Elements derzeit nur genau einmal registrieren. Mehrere Komponentenversionen nebeneinander ließen sich also nur durch versionierte Komponentennamen (z.B. <my-button-2>) realisieren – ein Antipattern. Die spätere Neuregistrierung einer Web Component, etwa um zur Laufzeit geänderte Versionsabhängigkeiten zu erfüllen, ist nicht möglich. Abhilfe soll hier die Scoped Custom Element Registry schaffen, die bei der Web Platform Incubator Community Group (WICG) vorgeschlagen wurde. Damit ist eine Komponentenregistrierung in untergeordneten Anwendungsscopes möglich. Ein Polyfill ist verfügbar, implementiert ist das Konzept bislang aber in keinem Browser.

Aufgrund der vielen Schnittgrenzen kann der Micro-Frontend-Ansatz schließlich selbst zum Problem werden: Typische Anforderungen, die den Einsatz von Micro-Frontends bedingen, sind hochmodulare Umgebungen mit mehreren Zielanwendungen oder Apps, die von mehreren organisatorisch getrennten Teams mit unterschiedlichen Vorerfahrungen zeitgleich entwickelt werden sollen. Liegt das nicht vor, sind Entwickler mit einem durch passende Architekturmittel gut strukturierten Monolithen eventuell besser aufgehoben.

Wenn wirklich ein Micro-Frontend-Ansatz gebraucht wird, stellen Web Components eine gute Option zur Umsetzung dar. Da sie im selben JavaScript-Kontext ausgeführt werden, sollten nur eigene Komponenten verwendet werden oder nur solche, deren Hersteller vertraut wird. Dann können unterschiedliche Entwicklerteams gleichzeitig unter Zuhilfenahme unterschiedlichster Frameworks eine oder mehrere Anwendungen entwickeln.

()