Web Components (Teil 2) – Einbindung in React

Im ersten Teil dieser Artikelreihe haben wir uns angeschaut, wie man eigene Web Components baut. Nun schauen wir uns die Einbindung in React-Anwendungen an.

Ihrer Idee nach sind Web Components unabhängig von JavaScript-Frameworks einsetzbar. Während dies beispielsweise bei Angular auch mit wenigen Handgriffen ohne Probleme funktioniert, sieht die Situation bei React leider etwas anders aus.​ Warum das so ist und wie man das Problem lösen kann, wird im Folgenden näher erläutert.

Prinzipiell lassen sich Web Components auch in React vollständig nutzen. Allerdings muss man für bestimmte Fälle zusätzlichen Aufwand betreiben und von üblichen React-Konventionen abweichen. Die Benutzung entspricht nicht mehr unbedingt dem, was React-Entwicklerinnen und -Entwickler erwarten würden.

Im Wesentlichen gibt es zwei Problemfelder: Einerseits handelt es sich dabei um das Problem „Attribute vs. Properties“, welchem wir uns in diesem Artikel widmen. Andererseits gibt es das Problem der „Custom-Events“ – dieses wird im nächsten Teil dieser Reihe behandelt.

Problembeschreibung „Attribute vs. Properties“

Wie wir im ersten Teil der Reihe gesehen haben, gibt es zwei Möglichkeiten, um Daten an eine Web Component zu übergeben – als HTML-Attribut oder als JavaScript-Property.

In diesem Code-Beispiel wird der „value“ als Attribut im HTML definiert:

<my-component value="something"></my-component>

Hier wird dagegen mittels JavaScript das gleichnamige Property gesetzt:

const myComponent = document.createElement("my-component")

myComponent.value = "something"

In JavaScript ist es aber auch möglich, explizit das Attribut zu setzen:

myComponent.setAttribute("value", "something")

JavaScript ist in dieser Hinsicht also flexibler, denn in HTML sind nur Attribute möglich – Properties lassen sich nicht in HTML setzen.

Wichtig zum Verständnis ist hierbei: Ob und wie Attribute und Properties von der Komponente verarbeitet bzw. berücksichtigt werden, liegt vollständig in der Implementierung der Komponente. Es gibt zwar die Best Practice, im Regelfall sowohl Attribute als auch Properties anzubieten und diese synchron zu halten, aber technisch ist niemand daran gebunden. Es wäre daher ohne Weiteres möglich, entweder nur Attribute oder nur Properties zu akzeptieren oder die beiden mit völlig unterschiedlichen Namen zu versehen (womit man aber sicherlich den Unmut der Benutzerinnen und Benutzer der Komponente auf sich ziehen würde).

Auf der anderen Seite gibt es jedoch auch handfeste Gründe, in manchen Fällen von dieser Best Practice bewusst abzuweichen.

Ein wichtiger Faktor ist, dass Attribute und Properties unterschiedlich mächtig sind: Attribute erlauben nur solche Werte, die als String repräsentiert werden können, d. h. Strings und Zahlen. Außerdem kann man durch die An- bzw. Abwesenheit eines Attributes auch Boolean-Werte abbilden. Komplexere Daten wie JavaScript-Objekte oder Funktionen können nicht als Attribut übergeben oder müssten serialisiert werden.

Bei JavaScript-Properties gibt es diese Beschränkung naturgemäß nicht. Allerdings haben Properties den Nachteil, dass sie in der Benutzung stets imperativ und nicht deklarativ sind. Anstatt  wie bei HTML einfach deklarativ zu sagen, welchen Zustand man haben möchte, muss man Properties mittels Befehlen imperativ der Reihe nachsetzen. Aus Entwicklersicht ist das eher unschön, denn besonders durch Frameworks wie React und (mit leichten Abstrichen) Angular hat man sich an die Vorzüge von deklarativem Arbeiten gewöhnt.

Ein weiterer Unterschied zwischen Attributen und Properties betrifft die Performance: Sowohl Attribute als auch Properties werden nicht nur dafür genutzt, Daten von außen in die Komponente zu geben, sondern auch, um auf Informationen der Komponente zugreifen zu können. Ein schönes Beispiel hierfür ist der Standard-HTML-Tag <video>, welcher die aktuelle Wiedergabeposition des abgespielten Videos mittels der JavaScript-Property „currentTime“ anbietet. Bei Abfrage dieser Properties erhält man die Position in Sekunden als Dezimalzahl. Ein dazu passendes HTML-Attribut existiert dagegen nicht. Ein solches Attribut müsste andernfalls ständig mit der aktuellen Abspielzeit aktualisiert werden, was im DOM eine relativ kostspielige Operation wäre. Die Abfrage über ein JavaScript-Property lässt sich dagegen recht performant lösen, da hierfür eine Lazy-Getter-Methode implementiert werden kann, die nur anspringt, wenn die Position tatsächlich abgefragt wird.

Wir haben bei Web Components somit zwei unterschiedliche Mechanismen für einen sehr ähnlichen Zweck, die sich dennoch in einigen Aspekten recht deutlich unterscheiden.

AttributeProperties
deklarativimperativ
String, Number, BooleanString, Number, Boolean, Date, Object, Function

React Props

Bei React sieht die Sache etwas übersichtlicher aus: React kennt lediglich so genannte „Props“. Da React einen starken Fokus auf deklaratives Programmieren legt, ähnelt die Benutzung der von HTML-Attributen:

<MyComponent value="something" />

React-Props sind aber nicht auf bestimmte Datentypen beschränkt, sondern erlauben das Übergeben von beliebigen Daten und auch von Funktionen. Hierfür wird anstelle der Anführungsstriche eine Syntax mit geschwungenen Klammern benutzt:

<MyComponent
    aDate={ new Date() }
    aNumber={ 12 }
    aComplexObject={ {firstname: "Hugo", lastname: "Meier" } }
    aFunction={ () => console.log("some action") }
/>

In gewisser Weise kombiniert React die jeweils positiven Aspekte von Attributen und Properties in einem einzigen Konzept. 

In der Komponente kommen die Daten in einem „props“-Objekt an, welches die übergebenen Werte als Key-Value-Paare enthält:

const MyComponent = (props) => {
    const aDate = props.aDate
    const aNumber = props.aNumber
    const aComplexObject = props.aComplexObject
    const aFunction = props.aFunction
    //...
}

Oder etwas kompakter mittels destructuring:

const MyComponent = ({ aDate, aNumber, aComplexObject, aFunction}) => {
    // ...
}

Als React-Entwickler muss ich sagen, dass mir persönlich die React-Variante mit Props deutlich besser gefällt als die Unterscheidung zwischen Attributen und Properties mit ihren jeweiligen Eigenarten bei Web Components – dies ist aber Geschmackssache.

Web Components in React

Nun ist die API von Web Components aber nun mal so, wie sie ist. Die Frage ist daher: Was passiert, wenn man eine Web Component in React benutzt? Werden „props“ als Attribute oder Properties an die Web Component weitergereicht?

Zunächst entscheidet React anhand der Groß- und Kleinschreibung des Tags, ob es sich um eine React-Komponente (beginnt mit Großbuchstaben) oder einen HTML-Tag handelt, worunter auch Web Components zählen. Mit Ausnahme einiger Sonderfälle bei einigen Standard-HTML-Tags setzt React Props bei HTML-Tags und Web Components immer mittels ​„setAttribute“​. Das heißt, dass die Benutzung von Attributen bei Web Components in React keine Probleme bereitet. Anders sieht es aus, wenn explizit JavaScript-Properties benutzt werden müssen, z. B. weil komplexe Daten oder Funktionen in die Web Component hineingereicht werden sollen. Dies lässt sich gegenwärtig mit React nicht deklarativ umsetzen. In gefühlt 90 % der Fälle stellt dies kein Problem dar, da es, wie oben bereits angemerkt, als Best Practice gilt, Attribute und Properties synchron zu halten und möglichst beide Varianten zu unterstützen. Nur in den restlichen 10 % der Fälle, in denen Properties notwendig sind, weil sich entweder die Autorinnen und Autoren der Web Component nicht an die Best Practice gehalten haben oder ein anderer Grund die Nutzung von Attributen verhindert, müssen wir uns etwas einfallen lassen.

Das heißt allerdings nicht, dass solche Web Components überhaupt nicht in React genutzt werden können! Wir können lediglich nicht den üblichen, rein deklarativen Weg gehen, sondern müssen auf die von React ebenfalls unterstützte, imperative API zurückgreifen. Wie dies funktioniert, wollen wir uns im Folgenden anschauen.

React abstrahiert von konkreten Instanzen von DOM-Knoten. Auch unabhängig von Web Components muss man aber in manchen Fällen direkt auf DOM-Knoten zugreifen, beispielsweise wenn eine Methode wie „.focus()“ aufgerufen werden soll. Für diesen Zweck nutzt React so genannte ​„Refs“​und genau diesen Mechanismus können wir auch für das Setzen von JavaScript-Properties an unseren Web Components benutzen. Im Code sieht das z. B. so aus:

import React, { useRef, useEffect } from "react"

const MyReactComponent = () => {
    const elementRef = useRef(null)

    useEffect(() => {
        if(elementRef.current) {
            elementRef.current.someProperty = "value"
        }
    }, [elementRef])

    return <my-custom-element ref={elementRef} />
}

Mit „const elementRef = useRef(null)“ erstellen wir eine Art Container, in die React nach dem Rendern die Referenz zum DOM-Knoten packt. „useEffect​“ kann dazu genutzt werden, eine Funktion auszuführen, sobald bestimmte Variablen verändert wurden. Dazu geben wir die „elementRef​„-Variable (in ein Array gewrappt) als zweiten Parameter an die​ „useEffect„-Hook-Funktion. Sobald React die Komponente das erste Mal gerendert hat, wird​ die angegebene Funktion ausgeführt, so dass unser Property entsprechend gesetzt wird. Wie man sieht, ist der Code doch um einiges umständlicher als lediglich ein Attribut direkt am Tag zu setzen. Das Beispiel zeigt aber, dass es eben doch möglich ist, Web Components in React zu nutzen. Im vierten Teil dieser Artikelreihe werden wir uns noch eine andere Variante anschauen, die besonders bei größeren Anwendungen, in denen bestimmte Web Components immer wieder eingesetzt werden sollen, besser skaliert. Im nächsten Artikel der Reihe schauen wir uns aber zunächst das zweite Problem von Web Components mit React genauer an: Die Verarbeitung von Custom-Events.

Fazit

Als Zwischenfazit lässt sich feststellen, dass die Situation von Web Components mit React kompliziert ist. Auf der einen Seite ist React hervorragend für die Entwicklung von umfangreichen Web-Anwendungen geeignet und daher auch weit verbreitet. Auf der anderen Seite ist es äußerst ärgerlich, dass React bei einer modernen Web-Technologie wie Web Components solche Probleme hat.

Als Grund hierfür lassen sich mindestens zwei Faktoren nennen: Zum einen entstand React zu einer Zeit, in der Web Components bzw. „custom elements“ noch eine bloße Idee und weit von der praktischen Umsetzung entfernt waren. Gleichzeitig legt das React-Team großen Wert auf Abwärtskompatibilität und schreckt verständlicherweise vor inkompatiblen Änderungen in der Art und Weise, wie React-Komponenten geschrieben werden, zurück. Die Diskussion dazu, welche Optionen im Raum stehen, um React kompatibel zu Web Components zu machen, kann bei Interesse im Issue-Tracker des Projekts​ verfolgt werden.

Der zweite Faktor, den ich hervorheben möchte, ist: Die Konzepte von Web Components und React unterscheiden sich relativ stark voneinander, wenn es darum geht, wie Komponenten benutzt werden. React ist vollständig auf deklaratives Programmieren ausgelegt, während Web Components und auch Standard-HTML-Tags eine Mischform vorsehen, die teilweise deklarativ, an einigen Stellen aber eben auch zwingend imperativ ist. Und da React-Entwicklerinnen und -entwickler genau diesen deklarativen Charakter von React mögen, kann es nicht die Lösung sein, die imperative API von Web Components einfach blind zu übernehmen. Stattdessen müssen Wege gefunden werden, wie eine Zusammenarbeit zwischen diesen beiden „Welten“ möglich ist. Leider dauert der Prozess dieser Lösungssuche mittlerweile schon relativ lange an und zwischenzeitlich schien die Diskussion innerhalb der Community der React-Entwicklerinnen und -Entwickler ein bisschen eingeschlafen zu sein.

Es bleibt daher nur zu hoffen, dass dieser Prozess wieder Fahrt aufnimmt, so dass Web Components in Zukunft auch in React-Projekten einfach und ohne umständliche Umwege eingesetzt werden können. 

Web Components (Teil 1) – Wie man eigene Komponenten baut

So genannte „Web Components“ sind eine Möglichkeit, wiederverwendbare UI-Komponenten für Web-Anwendungen zu bauen. Anders als bei etablierten Single-Page-App-Frameworks wie React oder Angular basiert das Komponenten-Modell aber auf Web-Standards. Da SPA-Frameworks aber weit mehr leisten als nur Komponenten zu bauen, stehen Web Components nicht in unmittelbarer Konkurrenz zu den etablierten Frameworks. Sie können diese aber sinnvoll ergänzen. Insbesondere dann, wenn Komponenten über Anwendungen mit verschiedenen Technologie-Stacks hinweg wiederverwendet werden sollen, können Web Components einen guten Dienst leisten.

Im Detail verbergen sich aber doch einige Tücken, wenn es um den Einsatz von Web Components in Single-Page-Anwendungen geht: Während die Einbindung in Angular-Anwendungen relativ einfach funktioniert, gibt es insbesondere bei React-Anwendungen einiges zu beachten.

Ob die „Schuld“ hierfür nun bei React oder dem Web-Components-Standard liegt, kommt auf die Perspektive an und ist nicht ganz so leicht zu beantworten. Es gibt aber auch Aspekte, bei denen Web Components auch in ihrer Kernkompetenz, dem Bauen von Komponenten den Kürzeren ziehen. Denn manches ist im Vergleich, z. B. mit React, unnötig kompliziert oder unflexibel.

Abbildung 1: Web Components und SPA-Frameworks

In dieser Artikelreihe soll es um diese und weitere Aspekte beim Zusammenspiel von Web Components und SPA-Frameworks, insbesondere React, gehen. Im ersten Teil der Reihe liegt der Fokus aber zunächst nur auf Web Components, was sich hinter dem Begriff verbirgt und wie man Web Components baut.

Was sind Web Components und wie baut man eigene Komponenten?

Hinter dem Begriff „Web Components“ verbergen sich mehrere separate HTML-Spezifikationen, die verschiedene Aspekte beim Entwickeln eigener Komponenten behandeln. Es gibt also nicht „den einen“ Standard für Web Components, sondern es handelt sich um eine Kombination von mehreren Spezifikationen.

Die beiden wichtigsten sind „Custom Elements“ und „Shadow DOM“. Die Custom-Elements-Spezifikation beschreibt u. a. die JavaScript-Basis-Klasse „HTMLElement“, von welcher eigene Komponenten abgeleitet werden müssen. Diese Klasse stellt zahlreiche Lifecycle-Methoden bereit, mit denen auf diverse Ereignisse im Lebenszyklus der Komponente reagiert werden kann. Beispielsweise lässt sich programmatisch darauf reagieren, dass die Komponente in einem Dokument eingehangen oder Attribute der Komponente gesetzt wurden. Entwickler und Entwicklerinnen einer Komponente können daraufhin die Darstellung der Komponente aktualisieren. Außerdem gehört zu Custom Elements die Möglichkeit, eigene Komponenten-Klassen unter einem bestimmten HTML-Tag zu registrieren, damit die Komponente anschließend im gesamten Dokument zur Verfügung steht.

Hinter „Shadow-DOM“ verbirgt sich eine Technik, mit der für eine Komponente ein eigener DOM-Baum angelegt werden kann, der vom restlichen Dokument weitestgehend isoliert ist. Das bedeutet, dass zum Beispiel CSS-Eigenschaften, die global im Dokument gesetzt wurden, nicht im Shadow-DOM wirksam sind und in die andere Richtung auch CSS-Definitionen innerhalb einer Komponente keine Auswirkungen auf sonstige Elemente im Dokument haben. Das Ziel ist eine bessere Kapselung der Komponenten und die Vermeidung von unerwünschten Seiteneffekten beim Einbinden von fremden Webkomponenten.

Im folgenden Code-Block ist eine einfache Hallo-Welt-Komponente zu sehen, die ein Property für den Namen der zu grüßenden Person enthält.

class HelloWorld extends HTMLElement {

    person = ""

    constructor() {
        super();

        this.attachShadow({mode: "open"})

        this.shadowRoot.innerHTML = `
            <div>
                <p>Hello <span id="personGreeting"></span></p>
            </div>
        `
    }

    static get observedAttributes() {
        return ['person']
    }

    attributeChangedCallback(name, oldValue, newValue) {
        if(name === "person") {
            if(this.person !== newValue) {
                this.person = newValue
                this.update()
            }
        }
    }

    update() {
        this.shadowRoot.querySelector("#personGreeting").textContent = this.person
    }

}
window.customElements.define("app-hello-world", HelloWorld)

Im Konstruktor der Komponente wird zunächst für die Komponente ein eigener Shadow-DOM-Baum angelegt. Die Angabe „mode: open“ bewirkt, dass trotz der Shadow-DOM-Barriere von außen mittels JavaScript auf den DOM-Baum der Komponente zugegriffen werden kann.

Anschließend wird der „shadowRoot“, also der Root-Knoten des Shadow-DOM, entsprechend unserer Wünsche gestaltet – hier mittels „innerHTML“.

Mit „observedAttributes“ erklären wir, welche Attribute die Komponente haben soll bzw. bei welchen Attributen wir benachrichtigt werden möchten (wir können hier also auch Standard-Attribute wie „class“ angeben).

Die Benachrichtigung findet über die Methode „attributeChangedCallback“ statt, die als Parameter den Namen des geänderten Attributs sowie den alten und neuen Wert erhält. Da wir in unserem Fall nur ein einziges Attribut in „observedAttributes“ angegeben haben, wäre eine Prüfung auf den Namen des Attributs eigentlich nicht notwendig. Bei mehreren Attributen muss aber stets geschaut werden, welches Attribut gerade geändert wurde.

In unserem Fall prüfen wir zunächst, ob sich der neue Wert tatsächlich vom bisherigen unterscheidet (wir werden später noch sehen, wie das zustande kommen kann). Anschließend setzen wir die Property „person“, die wir als Klassenvariable angelegt haben, auf den Wert des übergebenen Attributs.

Um die Darstellung der Komponente zu aktualisieren wurde im Beispiel die Methode „update“ angelegt. Diese gehört nicht zum Custom-Elements-Standard, sondern dient hier nur dazu, die Update-Logik an einer Stelle zu sammeln. Darin holen wir das zuvor angelegte Span-Element mit der ID „person“ aus dem Shadow-DOM und setzen dessen Text auf den Wert der „person“-Property.

Abbildung 2: Shadow DOM

Als letzten Schritt sieht man im Code-Beispiel, wie unsere Komponenten-Klasse mit dem Tag-Namen „app-hello-world“ registriert wird. Wichtig ist hier, dass der Name mindestens ein Minus-Zeichen enthält. Diese Regel wurde geschaffen, um mögliche Namens-Kollisionen mit zukünftigen Standard-HTML-Tags zu vermeiden. Es hat sich daher als zweckmäßig erwiesen, ein sinnvolles Präfix für eigene Komponenten zu wählen, um so auch Kollisionen mit anderen Komponenten-Bibliotheken möglichst zu vermeiden (das im Beispiel gewählte Präfix „app“ dürfte in dieser Hinsicht kein gutes Vorbild sein). Ein wirklich sicherer Mechanismus zur Vermeidung von Konflikten existiert jedoch nicht.

Mittels Attribute haben wir nun also die Möglichkeit, einfache Daten in die Komponente hineinzureichen. Beim Thema „Attribute“ gibt es noch einige Besonderheiten und Fallstricke, die wir aber für den nächsten Teil dieser Artikelreihe aufheben wollen. Für diese allgemeine Einführung wollen wir es erst einmal dabei belassen.

Slots

Ein weiteres wichtiges Feature von Web Components, welches uns ebenfalls in einem späteren Teil der Reihe nochmal beschäftigen wird, sind die sogenannten Slots. Damit lassen sich HTML-Schnipsel an eine Komponente übergeben. Die Komponente entscheidet dann, wie sie die übergebenen Elemente darstellt. Wollen wir beispielsweise eine Hinweisbox bauen, die neben einem Text auch ein Icon darstellt und mit einem Rahmen umgibt, bietet es sich an, den Hinweistext nicht als Attribut, sondern mit einem Slot an die Komponente zu geben. Auf diese Weise sind wir nicht nur auf reinen Text beschränkt, sondern können beliebigen HTML-Content nutzen.

In der Anwendung kann das beispielsweise so aussehen:

<app-notification-box>
	<p>Some Text with additional <strong>tags</strong></p>
</app-notification-box>

Wir müssen also nur die gewünschten HTML-Tags als Kindelemente schreiben. Innerhalb der Komponente muss dafür ein <slot>-Element im Shadow-Root auftauchen. Anstelle des Slot-Elements wird beim Rendering der Komponente dann der übergebene Content angezeigt.

<div>
    <div>Icon</div>
    <div id="content">
        <slot></slot>
    </div>
</div>

Eine Komponente kann auch mehrere Slots enthalten. Damit der Browser aber entscheiden kann, welche HTML-Elemente er welchem Slot zuordnen soll, müssen in diesem Fall sogenannte „Named Slots“ benutzt werden, d. h. die Slots bekommen ein spezielles Name-Attribut. Nur höchstens ein Slot darf innerhalb einer Komponente ohne Name-Attribut vorkommen. Bei diesem spricht man vom „Default Slot“. In der Komponente kann das z. B. so aussehen:

<div>
    <div id="header">
        <h1>
            <slot name="header"></slot>
        </h1>
    </div>
    <div id="icon">
        <slot name="icon"></slot>
    </div>
    <div id="content">
        <slot><slot>
    </div>
</div>

Die Benutzung könnte dann z. B. so aussehen:

<app-notification-box>
    <p>Some Content</p>
    <span slot="header">A meaningful Header</span>
    <img slot="icon" src="..." alt="notification icon"/>
</app-notification-box>

Hier sieht man die Nutzung des „slot“-Attributs. Die Werte müssen zu den „name“-Attributen an den Slots innerhalb der Komponente passen. Folglich gehört dies zum Teil der öffentlichen API einer Komponente und muss entsprechend dokumentiert werden.

Events

Bisher haben wir nur gesehen, wie Daten in Komponenten hineingereicht werden können, jedoch noch nicht den umgekehrten Weg skizziert. Denn um wirklich interaktiv zu sein, müssen Entwickler und Entwicklerinnen auch die Möglichkeit haben, auf bestimmte Ereignisse zu reagieren und Daten von der Komponente entgegenzunehmen.

Für diesen Zweck dienen bei HTML Events. Und auch diesen Aspekt wollen wir uns in diesem Artikel nur kurz anschauen und später genauer unter die Lupe nehmen.

Web Components können sowohl Standard Events als auch Custom Events erzeugen.

Standard-Events sind dann nützlich, wenn die Art des Events so auch schon bei Standard-HTML-Elementen vorkommt und daher nicht neu erfunden werden muss, beispielsweise ein KeyboardEvent. Custom-Events sind dann sinnvoll, wenn zusätzliche Daten als Payload dem Event mitgegeben werden sollen. Wenn wir beispielsweise eine eigene interaktive Tabellenkomponente bauen, in der die Nutzenden einzelne Zeilen selektieren können, bietet es sich möglicherweise an, ein Event bei der Selektion auszulösen , welches als Payload die Daten der gewählten Zeile enthält.

Der Mechanismus zum Auslösen von Events ist für alle Arten von Events gleich. Dies ist im folgenden Code-Block zu sehen:

class InteractiveComponent extends HTMLElement {

    triggerStandardEvent() {
        const event = new Event("close")
        this.dispatchEvent(event)
    }

    triggerCustomEvent() {
        const event = new CustomEvent("some-reason", 
            { detail: { someData: "..." }}
        )
        this.dispatchEvent(event)
    }
}

Zur Erzeugung eines Events wird entweder direkt eine Instanz von „Event“ oder eine der anderen Event-Klassen (zu denen auch „CustomEvent“ gehört) erzeugt. Alle Event-Konstruktoren erwarten als ersten Parameter den Type des Events. Dieser Typ wird später auch benutzt, um Listener für diese Events zu registrieren.

Der zweite Parameter ist optional und stellt ein JavaScript-Objekt dar, welches das Event konfiguriert. Für CustomEvent ist beispielsweise das Feld „detail“ vorgesehen, um beliebige Payload-Daten zu übergeben.

Fazit

Der Artikel gibt eine kurze Einführung in das Thema „Web Components“ und mit den gezeigten Techniken können bereits eigene Komponenten gebaut werden. Natürlich gibt es noch zahlreiche weitere Aspekte, die bei der Entwicklung von Web Components beachtet werden müssen. Nicht umsonst füllt das Thema so manches Fachbuch. In dieser Artikelreihe wollen wir vor allem auf einige Fallstricke eingehen, die bei einzelnen Themen auftreten können und genauer beleuchten, wie diese umgangen werden können. Auch eine kritische Auseinandersetzung mit der Web-Components-API soll Teil dieser Serie werden. Insbesondere das Zusammenspiel mit SPA-Frameworks wird uns in den nächsten Artikeln beschäftigen.