- Web Components wirken wie das Browser-Pendant zu React-Komponenten, tatsächlich kommen sie aber eher einem Modell nahe, das bestehendes HTML in den Mittelpunkt stellt und um Funktionalität erweitert
- Der Kernunterschied liegt im Rendering vor der Ausführung von JavaScript: Statt Daten an ein leeres Custom Element zu übergeben, ist es natürlicher, bedeutungsvolles HTML in ein Custom Element einzubetten
- Eine HTML web component erweitert bestehendes Markup, während ein leeres Element, dessen Inhalt und Funktion vollständig JavaScript überlassen werden, eher einer JavaScript-Web-Component entspricht
- Wer aus der React-artigen Komponentenbildung das Ersetzen gewohnt ist, muss bei Web Components in Erweiterung (augmentation) denken: Inhalte bleiben erhalten, Funktionalität kommt hinzu
- Auf der Web-Plattform überleben gute Ideen oft langfristig dadurch, dass sie bestehende Technologien ergänzen statt verdrängen — ähnlich wie bei HTML5,
fetch oder Entwicklungen rund um TypeScript
Web Components und React-Komponenten ticken anders
- Der Name „Web components“ kann klingen, als wären sie das Gegenstück zu React-Komponenten auf der Web-Plattform
- Reacts JSX nutzt die Form
<MyComponent>, Web Components können die Form <my-component> verwenden
- Wer Web Components aber so baut wie React-Komponenten, wird schnell frustriert sein
- Beide Technologien unterscheiden sich darin, welche Funktionen und Nutzungsweisen ihr Design priorisiert
- Wenn man die eine wie die andere verwendet, gerät man leicht in Konflikt mit der natürlichen Ausrichtung der jeweiligen Technik
HTML-Web-Components eignen sich eher für Erweiterung als für Ersatz
- Eine typische React-Komponente kann so aussehen, dass Daten per Attribut an eine leere Komponente übergeben werden und JavaScript den gesamten Inhalt rendert
<UserAvatar
src="https://example.com/path/to/img.jpg"
alt="..."
/>
- Rein äußerlich lässt sich eine Web Component auf dieselbe Weise schreiben
<user-avatar
src="https://example.com/path/to/img.jpg"
alt="..."
></user-avatar>
- Die eigentliche Stärke von Web Components ist jedoch, dass Rendering vor JavaScript möglich ist
- React-Komponenten können auf diese Weise nicht funktionieren
- Deshalb passt statt einer leeren „Shell-Component“ besser ein Aufbau, bei dem der Kerninhalt in HTML formuliert und dann durch ein Custom Element um Funktionalität erweitert wird
<user-avatar>
<img src="https://example.com/path/to/img.jpg" alt="..." />
</user-avatar>
- Jeremys Unterscheidung in „HTML web components“ richtet den Blick darauf, ob ein Custom Element bestehendes Markup erweitert
- Wenn das Custom Element leer ist, ist es keine HTML-Web-Component
- Wenn es bestehendes Markup umschließt und erweitert, kommt es einer HTML-Web-Component nahe
- Eine „JavaScript web component“ ist eine Form, bei der Inhalt und Funktion eines leeren Elements vollständig von JavaScript abhängen
<user-avatar
src="https://example.com/path/to/img.jpg"
alt="..."
></user-avatar>
- Diese Form ist für Endnutzer ohne JavaScript bedeutungslos
- Eine HTML-Web-Component dagegen bewahrt auch ohne JavaScript Bedeutung und Inhalt; mit JavaScript wird darauf zusätzliche Funktionalität aufgebaut
<user-avatar>
<img src="https://example.com/path/to/img.jpg" alt="..." />
</user-avatar>
Im Web hält sich der Erweiterungsansatz länger
- Dass ein erweiternder Ansatz im Web gut passt, liegt daran, dass das Web von Natur aus robuste progressive enhancement fördert und sich für wiederholte Veränderungen an etwas so Großem wie dem Web eignet
- Gute Ideen aus Frameworks und Bibliotheken rund um das Web werden selbst dann, wenn sie in die Plattform einfließen, oft eher als Ergänzung übernommen als als vollständiger Ersatz bestehender Technik
- XHTML wollte HTML4 ersetzen, HTML5 wollte HTML4 ergänzen — und HTML5 hat gewonnen
- Networking-Bibliotheken wollten
XMLHttpRequest ersetzen, und ihre guten Ideen wanderten schließlich in den fetch-Standard
fetch existiert heute auch in vielen Umgebungen außerhalb des Browsers
- Gute Ideen aus Sass und jQuery sind ebenfalls in den Browser gewandert
- Auch gute Ideen aus TypeScript gelangen in den Browser, ohne bestehende Technik zu ersetzen, sondern indem sie sie erweitern
- Web Components kann man zwar als einen Prozess sehen, bei dem das Komponentenmodell von React in den Browser wandert, aber sie liegen näher daran, die bereits funktionierende Arbeitsweise des Webs zu ergänzen statt zu ersetzen
- Wenn man einen technischen Ansatz sucht, der lange Bestand hat, passt im Web Erweiterung und Verbesserung besser zur Richtung der Plattform als Ersatz
1 Kommentare
Meinungen auf Hacker News
Ich hatte gehofft, der Artikel würde erklären, was
user-avatartatsächlich tut oder bereitstellt, aber dazu kam am Ende nichts.Wenn darin nur Styling steckt, verstehe ich nicht, warum man nicht einfach eine CSS-Klasse verwenden sollte; außerdem wirkt es viel natürlicher, wenn
user-avatareinsrc-Attribut entgegennimmt, statt jedes Mal intern einimg-Tag einfügen zu müssen.Vue/React/Angular versuchen weniger, HTML zu „ersetzen“, sondern bauen eher auf HTML/CSS/JS auf; wenn alles auf einem Canvas gerendert würde, fände ich diese Behauptung überzeugender.
Auf Web Components hatte ich mich gefreut, als sie erstmals angekündigt wurden, aber die eingebauten Funktionen sind zu spärlich, und es fühlt sich nicht so an, als würden sie beim Bau von Web-Apps wirklich so helfen wie ein Framework.
Alternativen zu großen Frameworks, besonders Dinge wie htmlx, wirken wie etwas syntaktischer Zucker über der jQuery-Linie, was sich für den Bau von Web-Apps wie ein großer Rückschritt anfühlt.
Wenn mit „Web-App“ etwas wie Google Sheets gemeint ist, stimme ich zu; aber diese Anti-React-Strömung scheint eher die Praxis zu kritisieren, standardmäßig ein Framework aufzusetzen und von Anfang an damit zu bauen, statt solche Fälle.
Es gibt tatsächlich viele Websites, die nur „ein wenig Interaktion obendrauf“ brauchen.
Der zentrale Vorteil ist progressive Verbesserung: Da das
img-Tag ein Standardverhalten hat, kann man sich auf das grundlegende Rendering verlassen und nur die nötigen Teile mit Web Components „verstärken“.Die Komponente
details-utilsverstärkt das Verhalten der eingebauten HTML-Komponentedetail.Wenn JavaScript aus irgendeinem Grund deaktiviert ist, funktioniert die
detail-Komponente weiterhin wie gewohnt; wenn JavaScript aktiviert ist oder fertig heruntergeladen wurde, bekommt sie verbessertes Verhalten, etwa dass sie sich beim Klick außerhalb einklappt.Der wiederverwendbare Teil dieses Ansatzes ist genau diese Verhaltensverstärkung.
Durch diese Web Component des 11ty-Machers habe ich den Punkt des Artikels verstanden; der Teil, bei dem ich beim ersten Blick auf Web Components dachte: „Am Ende braucht man doch JavaScript, und ohne funktioniert es nicht“, taucht auch in Rich Harris’ Artikel an derselben Stelle auf: https://dev.to/richharris/why-i-don-t-use-web-components-2ci...
htmx erweitert vor allem das Paradigma von serverseitig gerendertem HTML, ohne JavaScript schreiben zu müssen, von vollständigen Seiten-Reloads hin zu partiellen Seitenaktualisierungen.
Wer mehr zur Idee von „HTML Web Components“ sehen möchte, kann auch diese Artikel lesen:
https://meyerweb.com/eric/thoughts/2023/11/01/blinded-by-the... – “So there you have it: a few thousand words on my journey through coming to understand and work with these fully-Light-DOM web components, otherwise known as custom elements. Now all they need is a catchy name, so we can draw more people to the Light Side of the Web.”
https://adactio.com/journal/20618 schlägt einen plausiblen Namen vor.
Weil es umständlich zu schreiben ist, braucht man am Ende ein leichtgewichtiges Framework über einem eingebauten Framework wie Lit, und Lit ist sogar größer als Preact.
Außerdem löst es reale Probleme wie State Management und Routing nicht, also wird man wahrscheinlich noch mehr dazuholen müssen.
Man kann zwar wiederverwendbare Komponenten bekommen, aber wenn man sich fragt, ob man in einer React-Umgebung eine Web Component einbinden würde, die intern Vue verwendet, ergibt das nicht wirklich Sinn.
Die Schönheit und Eleganz des Webs kamen aus seiner deklarativen Struktur, und dadurch entstanden Beobachtbarkeit und Änderbarkeit.
Shadow DOM fühlte sich für mich wie ein unternehmerischer Wunsch an, höhere Kapselungsbarrieren und Verlässlichkeit aufzubauen, und das war persönlich kein Ziel, das ich teile.
Dieser Artikel zeigt, wie Light-DOM-Arbeit komponiert werden kann.
Ich habe immer gedacht, dass Web Components oder Custom Elements ihr internes DOM selbst verändern, Kinder verschieben und neue Inhalte erzeugen können sollten.
Zum Beispiel könnte eine Seite oder ein Framework ein Icon einfügen, und ein User-Avatar-Element könnte Namen oder dekorative Elemente einfügen.
Eine Sorge bei Light DOM/HTML Web Components ist allerdings, dass Shadow DOM einige Performance-Vorteile bietet.
Dass CSS-Selektoren dadurch weniger Elemente durchsuchen müssen, kann ich mir als Entwickler gut vorstellen, und es wäre schön, wenn man diesen Vorteil irgendwie nutzen könnte.
Ich freue mich wirklich über einen leichtergewichtigen Blick auf Custom Elements und Web Components, und danke auch für die Links.
Die Formulierung „Kann vor JavaScript gerendert werden. React-Komponenten können das niemals“ lässt sich schwer so absolut stehen lassen; bei serverseitigem Rendering kann vor clientseitigem JavaScript gerendert werden.
Ich finde, das Beispiel ist zu simpel, um die Aussage des Autors zu belegen.
Eine Web Component, die Zustandsänderungen behandelt, wäre ein besseres Vergleichsobjekt gewesen, und die Argumentation wäre vermutlich überzeugender ausgefallen.
Es gibt Hydration-Lösungen, aber die sind meist schlechter, bringen überraschende Kompromisse mit sich und beeinträchtigen oft die Komponierbarkeit.
Wenn ich nur das Beispiel sehe, das ein
img-Tag umschließt, erschließt sich mir der Nutzen nicht wirklich; man kann gemeinsame Elemente bündeln und wiederverwenden, aber für Interaktion braucht man weiterhin JavaScript.Auch der alternative Bildtext im Beispiel ist heutzutage wegen Lokalisierung meist dynamisch, sodass ohne JavaScript Inhalte fehlen könnten.
Ich glaube, ich habe Web Components endlich verstanden: https://github.com/kennyfrc/cami.js
„No Build Steps, No Client-Side Router, No JSX, No Shadow DOM. We want you to build an MPA, with mainly HTML/CSS, and return HTML responses instead of JSON. Then add interactivity as needed.“
„Declarative templates with lit-html. Supports event handling, attribute binding, composability, caching, and expressions.“
Persönlich mag ich Klassen im Stil von React-Klassenkomponenten, mit einer von XState inspirierten eingebauten Zustandsmaschine.
https://github.com/codewithkyle/supercomponent/blob/master/s...
Die Richtung scheint ziemlich ähnlich zu sein, und die HTMX-Community könnte größer sein.
Falls du es ausprobiert hast, würde mich interessieren, was dir daran gefehlt hat.
„web components“ sind nicht eine einzelne Sache, und man erstellt auch nicht „a web component“.
„Web Components“ ist der Name der Web Components API, die drei Dinge zusammenfasst.
Was man tatsächlich erstellt, ist ein benutzerdefiniertes Element; dabei kann man Shadow DOM verwenden oder HTML-Templates nutzen.
Das Wichtigste der drei sind benutzerdefinierte Elemente.
Das Kernkonzept lautet: „mehr HTML-Elemente erstellen“; welche Attribute und JavaScript-APIs unterstützt werden, legst du also komplett selbst fest.
Wie man sie auf die Seite bringt, mit ihnen interagiert und auf Events hört, ist genau wie bei anderen HTML-Elementen.
Wenn du Webseiten auf die „alte Art“ schreiben kannst, weißt du bereits, wie man benutzerdefinierte Elemente verwendet; du musst nur noch lernen, wie man sie deklariert.
Ich habe vor Kurzem angefangen, Web Components ohne Build-Umgebung auszuprobieren.
Kein npm, bun oder webpack, keine Abhängigkeiten, und geschrieben in TypeScript.
IntelliJ kompiliert automatisch zu JavaScript, und die Browser-Ansicht injiziert während der Entwicklung einen kleinen Change-Detection-Handler für Live-Updates.
Bisher gab es keine Probleme.
Was Web Components auszubremsen scheint, sind HTML Modules.
Es wäre schön, zum Importieren von Web Components nicht auf
.js-Dateien, sondern auf.html-Dateien verlinken zu können; derzeit muss man aber, wenn man Templates oder etwas Komplexeres nutzen will, hässliche Injektionen wie.innerHtml = \...`` verwenden.Ich dachte, das würde ein Problem werden, aber die IDE parst Template-Strings ziemlich gut.
Und das ist auch nicht der einzige Grund, der Web Components ausbremst.
Die Behauptung „React ist kein Enhancement, sondern ein Ersatz“ überzeugt mich nicht so recht
Am Ende rendert auch React HTML-Elemente und hängt JavaScript-Event-Handler daran
Wenn man
imgin eine React-Komponente einwickelt, nimmt manimgja nicht seine Funktion weg, sondern fügt etwas obendrauf hinzu – also ein EnhancementDer Autor hat vielleicht in anderen React-Codebasen gearbeitet, aber meiner Erfahrung nach verwenden wir eingebaute Browser-Funktionen unverändert, wenn es keinen Grund gibt, es anders zu machen
Vielleicht hatten wir einfach Glück
Der Punkt ist, dass der Ansatz „HTML Web Component“ im Gegensatz zu React nicht von JavaScript abhängt, um mit dem Rendering zu beginnen
React ist aus Sicht des Browser-Renderings „Seite laden → Komponente laden“, Web Components sind eher „Seite laden → Basis-Rendering → Komponente laden“
Wer JavaScript deaktiviert hat, kann bei Web Components trotzdem etwas sehen, während er bei React möglicherweise gar nichts sieht; mit JavaScript kann es dann in einen weiterentwickelten Renderzustand übergehen
Wenn man zum Beispiel
onchangeeinem Element zuweist, liefert React nicht daschange-Event, sondern eher etwas wie eininput-EventTatsächlich ist es keines von beiden, sondern ein synthetisches Event, das näher an
inputals anchangeliegtWenn man wirklich
changemöchte, muss man eine Element-Referenz verwenden und den Handler in einem Effekt direkt anhängenWenn man mit React HTML vom Server zurückgibt, dann ist das Einwickeln von
imgin eine React-Komponente tatsächlich ein Enhancement des vorhandenen ElementsWenn aber alles clientseitig gerendert wird, lässt sich dieses
imgam Ende nicht von der React-Komponente trennenMeiner Erfahrung nach ist React großartig, wenn man ihm die gesamte Seitenstruktur von oben bis unten überlässt; schwierig kann es werden, wenn man es in eine bestehende Struktur einfügen will, etwa im Zusammenhang mit serverseitigem Rendering
Wenn man nach einem langlebigen Ansatz sucht, passt die Schlussfolgerung, Ergänzung und Verbesserung statt Ersatz zu wählen, auch zu meiner Erfahrung
Dank dieser Philosophie konnten meine Webprojekte lange bestehen, mit minimalem Wartungsaufwand und wenigen Abhängigkeiten
Web Components sollten eine Sache tun, während JavaScript-Frameworks eher ganze Ökosysteme sind
Ich habe eine Web-Component für einen Videoplayer gebaut, die verschiedene Eingaben akzeptieren kann; die komplexeste Eingabe war eine Torrent-Datei
Mit StencilJS [0] hätte ich sie auch nach Vue/React portieren können, aber sie war auch ohne das völlig brauchbar
Man fügt einfach das entsprechende Tag zusammen mit der aus
awesomePlayer.jsexportierten Klasse ein und erhält einen HTML5-Videoplayer zum Kopieren und Einfügen, der Torrents abspieltWenn möglich, empfehle ich außerdem sehr, bestehende HTML-Elemente nachzuahmen
Zum Beispiel habe ich
srcverwendet, weilvideoes so macht; dadurch kann die nutzende Seite damit interagieren, ohne erst die Dokumentation durchsuchen zu müssen[0] https://stenciljs.com/
Ich tue mich schwer damit, zuzustimmen, dass Frontend-Framework-Komponenten vollständig als Ersatz gedacht und nicht komponierbar seien
Oberflächlich mag das so wirken, aber in meinen Komponenten verwende ich viele Slots, und die Implementierung ist einfach und verhält sich natürlich
Web Components werden dagegen meist so demonstriert, dass sie riesige Mengen Code einfügen, um etwas wie einen Editor zu bauen
Slots in Web Components zu verwenden, war schmerzhaft: Man hängt viele Nodes manuell an, behandelt Templates als Strings und muss, sobald es etwas komplexer wird, sogar auf das
slotchange-Event hörenIm Grunde verwendet man dabei die DOM-API, und wenn diese API nicht so schrecklich wäre, wären wir gar nicht erst zu Frontend-Frameworks wie React gewechselt
Auch der Nebenbehauptung, XHTML sei gescheitert, weil es HTML nicht erweitert habe, stimme ich nicht zu
Meiner Ansicht nach scheiterte es, weil Anwendungen vollständig valide sein mussten und diese Validierung dem Client/Browser überlassen wurde
Hätte man echtes XHTML verwendet, hätte schon ein kleiner Fehler im Markup die Seite kaputtgemacht; deshalb haben zwar alle XHTML zur Zukunftssicherung validiert, aber kein Unternehmen hätte riskieren wollen, dass das eigene Geschäft daran zerbricht, dass ein einzelnes
p-Tag nicht korrekt geschlossen wurde