Angular vs. LitElement - Frameworkunabhängige WebComponents

Donnerstag, 7.1.2021

Angular Elements und LitElements im Vergleich

Dank ihrer Wiederverwendbarkeit und der Tatsache, dass sie unabhängig vom Framework funktionieren, werden WebComponents immer beliebter. Google bietet mit LitElement und Angular-Elements gleich zwei Lösungen, um WebComponents zu entwickeln. Dieser Beitrag erklärt das Vorgehen und wagt einen Vergleich der beiden Optionen.

Immer häufiger setzen unsere Kunden auf WebComponents, die von den meisten Browser mittlerweile vollständig unterstützt werden. Der große Vorteil ist, dass eine hohe Wiederverwendbarkeit möglich ist, da WebComponents unabhängig von verwendeten Frameworks, wie beispielsweise Angular, React oder Vue, eingesetzt werden können. Dies ist gerade in größeren Unternehmen von Vorteil, bei denen nicht alle Abteilungen die gleiche Frontendtechnologie nutzen wollen oder können. UI-Komponenten oder Komponenten mit wiederkehrender Businesslogik müssen so nur einmal erstellt werden.

Google hat mit LitElement eine sehr schmale Lösung entwickelt, die beim Entwickeln von WebComponents hilft und viele Komfortfunktionen liefert. Gleichzeitig bietet Google mit Angular-Elements aber auch die Möglichkeit WebComponents mit Angular selbst zu erstellen.

In diesem Beitrag möchte ich zeigen, wie man mit Angular-Elements eine WebComponent erstellt und das Ergebnis mit der gleichen, in LitElement umgesetzten Komponente vergleichen.

 

Angular Elements

Um eine WebComponent mit Angular-Elements zu erstellen, müssen wir ein paar Änderungen an einem "normalen" Angular-Projekt vornehmen. In diesem Beispiel nutzen wir Angular und die CLI in der Version 11. Damit wir uns nicht mit den ganzen Polyfills und Browsersonderlocken beschäftigen müssen, verwenden wir JavaScript in der Version ES6 (ECMAScript 2015) oder höher. Ab diesem Zeitpunkt sind Klassen und WebComponents nativ möglich. Natürlich muss der Browser dies auch unterstützen: Firefox, Chrome und der neue Edge tun dies in der aktuellen Version. Auch nutzen wir nicht JavaScript direkt, sondern TypeScript, wie die Angular-CLI es auch im Standard verwendet.

Als Erstes erstellen wir ein neues Angular-Projekt.

ng new angular-textinput --routing=false --minimal --strict --interactive=false

Damit wir aus den Angular-Komponenten WebComponents erstellen können, fügen wir das dafür nötige Package hinzu.

ng add @angular/elements

Der add-Befehl fügt automatisch ein Polyfill hinzu, das wir wieder entfernen (import 'document-register-element' in der Datei polyfill.ts löschen). Jetzt können wir ganz normal unsere Komponente in Angular entwickeln. Zu beachten ist nur, dass wir in den Komponenten die Option encapsulation auf ShadowDom stellen. Für eine kompaktere Darstellung habe ich Inlinetemplates und -styles verwendet, das ist aber nicht nötig.

ng g c angular-textinput --flat --inline-style --inline-template --skip-tests --display-block --view-encapsulation=ShadowDom

Die Komponente rendert einen Textinput und zeigt, wenn eine Maximallänge angegeben ist, wie viel Zeichen bereits verwenden worden sind. Als Eingabe kann neben der besagten Maximallänge noch das Label und der Placeholder gesetzt werden, als Output schickt die Komponente ein Custom-Change- und Custom-Input-Event. Das Ganze sieht dann wie folgt aus:



Damit die Komponente jetzt eine WebComponent wird, müssen wir diese mit der bereitgestellten Funktion von Angular-Elements "umwandeln". Da wir das Angular-Projekt nur zum Erstellen der Komponente verwenden, ändern wir das app.module so ab, dass es nicht Angular startet, sondern die WebComponent erstellt. Das modifizierte app.module sieht wie folgt aus:



Damit wir später beim Verwenden unserer WebComponent nur eine Datei einbinden müssen, ergänzen / modifizieren wir folgende Scripts in der package.json:

"build": "ng build --prod --output-hashing=none"

und

"package": "cat ./dist/angular-textinput/{runtime,polyfills,main}.js > angular-textinput.js && ls -lah angular-textinput.js"

Wobei hier natürlich der passende Pfad gewählt werden muss, je nachdem wie man das Projekt genannt hat.

Ich hatte vorher geschrieben, dass wir keine Polyfills brauchen, dies ist nur halb wahr gewesen. Angular baut das Projekt nicht, wenn nicht das zone-js Polyfill für die Changedetection eingebunden ist, daher muss dies mit ausgeliefert werden.

 

LitElement

Mit LitElement sieht die Komponente an sich sehr ähnlich aus (abgesehen von den Unterschieden in der Syntax). Auf das Erstellen von Komponenten mit LitElement gehe ich an dieser Stelle nicht weiter ein, kann aber in unserer Blogreihe zu diesem Thema nachgelesen werden: https://blog.viadee.de/web-components-teil-1. Da LitElement eine Bibliothek zum Erstellen von WebComponents ist, muss hier auch nichts "extra" unternommen werden. Die Komponente ist direkt eine WebComponent (wichtig auch hier: ES6 oder höher). Die fertige Implementierung sieht in TypeScript wie folgt aus:



Mit beispielsweise Rollup lässt sich die Komponente und LitElement zusammenfügen und "minimieren".

 

Verwendung der WebComponents

Damit wir die WebComponents jetzt testen können, binden wir diese einfach in eine HTML-Seite über ein <script>-Tag ein. Danach können wir die Elemente wie normale HTML-Elemente nutzen und mit JavaScript beispielsweise auf Events reagieren.



Wichtig ist, dass man die HTML-Datei über einen Server ausliefert (z.B. über @web/dev-server), weil der Browser sonst wegen CORS die Moduldateien (type="module" im Script-Tag) nicht lädt.

 

Fazit

Auf beiden Wegen kommen wir zum Ziel: Wir erstellen eine WebComponent, welche ganz ohne ein Framework oder in jedem¹ anderen Framework eigesetzt werden kann. So kann beispielsweise jede Abteilung eine andere Frontendtechnologie einsetzen und trotzdem die gleichen Komponenten verwenden. Gerade für UI-Komponenten ist dies sehr hilfreich, so sehen alle entwickelten Anwendungen gleich aus.

Angular LitElement
Pro
  • Mächtigkeit (Formshandling, Routing, RXJS out of the box)
  • Weite Verbreitung
  • Gute Dokumentation
  • Große Community
  • Eventuell schon vorhandene Komponenten / Knowhow in Angular
Pro
  • Kleines Bundle²
  • Kleine Bibliothek (theoretisch selbst wartbar)
  • Hohe Performance
  • Schnelle Einarbeitung (u.a. keine neue Templatesprache)
  • Genau für diesen Zweck entwickelt
Contra
  • Großes Bundle² (vor allem wenn Forms, Routing, RXJS, etc, verwendet wird)
  • Vendor-Lockin
     
Contra
  • Recht neu / geringe Verbreitung
  • Kleine Community
  • "Extras" (Formshandling, Routing, RXJS) müssen manuell hinzugefügt werden

Wann auf welche Technologie gesetzt werden sollte, kann man wie so oft pauschal schwer beantworten. Beide Möglichkeiten führen zum Ziel und haben ihre Vor- und Nachteile. Welche Technologie eingesetzt werden sollte, muss daher im jeweiligen Kontext des Unternehmens / der Abteilung abgewogen werden.

1 Zumindest in den meisten Frameworks. Angular, React, Vue und plain Javascript funktionieren in jedem Fall.
2 In unserem Test ist die Angular-WebComponent ca. 166 KB groß und die Lit-WebComponent ca. 31 KB.

Weiterführende Links:


Sie möchten sich mit uns zu dem Thema WebComponents austauschen? Gerne stellen wir Ihnen auch den Quellcode aus dem hier beschriebenen Demo-Projekt zur Verfügung. Kommentieren Sie einfach unter diesem Beitrag oder kontaktieren uns per Mail.


 


zurück zur Blogübersicht

Diese Beiträge könnten Sie ebenfalls interessieren

Keinen Beitrag verpassen – viadee Blog abonnieren

Jetzt Blog abonnieren!

Kommentare

Andre Rauer

Andre Rauer

Andre Rauer ist Berater bei der viadee und als Softwareentwickler und Business Analyst tätig. Sein Fokus liegt auf den Bereichen Mobile- und Web-Engineering, Java Enterprise-Anwendungen, sowie BPMN-Modellierung.