Avatar von Lestard_
  • Lestard_

552 Beiträge seit 05.10.2010

Erfahrung mit Web Components

Ich bin React-Entwickler (auch Angular aber das gefällt mir nicht so wirklich) und seit einiger Zeit arbeite ich auch verstärkt mit Web Components (konkret mittels lit-element).
Bei uns geht es aber eher darum, dass die Anwendungen selber mit Angular gebaut werden und zwischen diesen Anwendungen eine gemeinsame Komponenten-Bibliothek wiederverwendet werden soll.
Mein Zwischenfazit ist aber eher verhalten. Auf der einen Seite sind die Vorteile natürlich verlockend: Man baut Komponenten, die in verschiedenen Frameworks nutzbar sind.
Aus der Brille eines React-Entwicklers kann ich über die Möglichkeiten von Web-Components aber nur müde lächeln. React ist wesentlich flexibler, erlaubt kompakteren und fehlerärmeren Code und macht einfach mehr spaß.
Beispiele, die mir bei Web-Components nicht gefallen:

1. Es gibt den "<slot>"-Mechanimus, mit dem man Kind-Elemente in eine Web-Componente verarbeiten kann. Das sieht bei der Benutzung dann so aus:

<my-component> <div>Child</div> </my-component>

Der Mechanismus ist aber extrem primitiv und lässt wenig Spielraum für Anpassungen. Damit das funktioniert muss irgendwo im Shadow-DOM der Komponente ein "<slot>"-Element auftauchen und genau an die Stelle erscheint dann das Child-Element. Mehr geht im Prinzip nicht.

Möchte man dagegen das Child-Element dynamisch verwenden, beispielsweise transformieren oder sonst wie nutzen, ohne es direkt anzuzeigen, hat man ein Problem. Wir hatten z.B. die Idee, eine eigene Listen-Komponente zu bauen. Ziel war in etwa diese Benutzung:

<my-list> <div>Element 1</div> <div>Element 2</div> Element 3 <span>Element 4</span> </my-list>

Der Nutzer legt einfach beliebig viele Kind-Elemente in die Komponente und wir würden die dann intern in eine "<ul><li>...</li></ul>" Struktur einpflegen. Keine Chance.
Man könnte eventuell eine Magie machen, bei der das slot-Element versteckt wird und die Kind-Elemente herauskopieren und in die Ziel-Struktur einbauen, aber das bringt wieder einen Rattenschwanz an anderen Problemen mit sich. Wir haben es letztlich aufgegeben weil alle "Lösungen" relativ massive Nebenwirkungen hätten.

Bei React wäre das überhaupt kein Problem. Bei React gibt es einfach ein "children"-Prop als Parameter der Komponente und was ich damit mache ist allein mir überlassen. Drüber-Iterieren und in "<li>"-Elemente wrappen wäre überhaupt kein Problem.

Das Listen-Ding war eines der nervigsten aber es gab einige weitere, wo ich über diesen Slot-Mechanismus nur den Kopf geschüttelt hatte.

2. Web-Componenten haben "Attribute" und "Properties". Attribute ist das, was man in HTML-Code hinschreibt, also z.B. "<hello-world name="Luise">". Attribute erlauben aber im Prinzip nur Strings als Typen (auch Boolean und Number, weil die von/zu String gecastet werden können) aber keine komplexen Typen wie Objekte oder Funktionen. Properties sind das, was man per DOM manipulieren kann, also z.B.

const ref = document.querySelector("hello-world") ref.name = "Luise"

Als Best-Practise gilt, dass Attribute und Property übereinstimmen sollen und auch miteinander synchronisiert werden, d.h. wenn ich das Attribut ändere, ist auch das Property angepasst.

Dieser Dualismus ist aber ein Quell von Fehlern und Ungereimtheiten. Zum einen muss man dafür sorgen, dass zu jedem Attribut auch wirklich ein entsprechendes Property existiert (wobei unterschiedliche Namens-Einschränkungen gelten: Das Attribut "some-value" ist kein gültiger Bezeichner für ein Property und müsste z.B. "someValue" heißen). Bei der Synchronisierung kann es zu Schwierigkeiten kommen, z.B. wenn bestimmte Werte als ungültig definiert werden.

Es sorgt aber auch für einen imperativen Programmierstil, weil man Properties normal nur über die Instanz eines Elements setzen kann. Eigentlich will ich aber einen Deklarativen Stil haben, also eigentlich nur Attribute nutzen. Das geht aber nicht immer, wegen der genannten Einschränkungen. Einige Frameworks wie lit-element haben eine Sondersyntax erfunden um Properties auch deklarativ zu setzen. Aber eigentlich war es ja der angepriesene Vorteil, dass man keine Frameworks mehr braucht.

Bei React gibt es nur "Props", die wie Attribute deklarativ gesetzt werden, wobei React-Props beliebige Typen erlauben. Ich kann mit React vollständig deklarativ arbeiten und muss mir keine Gedanken machen, ob ich jetzt ein Property oder Attribut nutzen muss.

3. Web-Components sind stark Objektorientiert, d.h. man erbt von der Basis-Klasse und überschreibt verschiedene Lifecycle-Methoden. Das sorgt aber nicht-trivialen Komponenten regelmäßig für Probleme und Bugs weil das Zusammenspiel dieser Methoden halt nicht immer so klar ist. Und es macht das Nachverfolgen dessen, was in der Komponente gerade passiert, relativ schwierig. Eventuell kann man an der Stelle aber auch mit besseren Frameworks arbeiten, die die inherente Komplexität etwas kapseln.

Mein persönliches Fazit ist, dass Web-Components durchaus ihre Berechtigung haben wenn man Komponenten über mehrere Frameworks hinweg benutzen will.
Aber ein React oder Angular ersetzen sie zuminest aktuell noch nicht. Nicht nur, weil beide wesentlich mehr machen als nur Komponenten zu bauen aber selbst in diesem Bereich des Komponenten-Bauens können Web-Componentes mich persönlich noch nicht so richtig überzeugen.

Bewerten
- +