2 Punkte von GN⁺ 2023-11-14 | 1 Kommentare | Auf WhatsApp teilen
  • 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

 
GN⁺ 2023-11-14
Meinungen auf Hacker News
  • Ich hatte gehofft, der Artikel würde erklären, was user-avatar tatsä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-avatar ein src-Attribut entgegennimmt, statt jedes Mal intern ein img-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.

    • Ich stimme zu, dass „Alternativen zu großen Frameworks wie syntaktischer Zucker über jQuery wirken“, aber warum das für den Bau von Web-Apps eine völlig falsche Wahl sein soll, ist unklar.
      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.
    • Ich finde, Eric Meyers Artikel zeigt die Absicht viel besser: https://meyerweb.com/eric/thoughts/2023/11/01/blinded-by-the...
      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“.
    • Wegen der fehlenden konkreten Beispiele wirkt der Artikel ein wenig wie ein Gedanke unter der Dusche.
    • Ein Beispiel, das den Kern des Artikels konkreter zeigt, ist dieses hier besser: https://www.zachleat.com/web/details-utils
      Die Komponente details-utils verstärkt das Verhalten der eingebauten HTML-Komponente detail.
      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...
    • Ich weiß nicht, ob du htmx ausprobiert hast, aber es behandelt ein anderes Problem als die clientseitige JavaScript-User-Experience, die jQuery löste; daher scheint die Kritik daneben zu liegen.
      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.

    • Ich verstehe den Punkt nicht so recht.
      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.
    • Ich freue mich wirklich über die Strömung, die Web Components ohne Shadow DOM vorantreibt.
      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.
    • Vielleicht könnte man den plausiblen Namen noch weiter verkürzen und sie HTML components nennen.
  • 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.

    • Guter Punkt; umgekehrt kann man auch sagen, dass Web Components das nicht können, weil sie vor dem Laden der Seite per JavaScript registriert werden müssen.
      Es gibt Hydration-Lösungen, aber die sind meist schlechter, bringen überraschende Kompromisse mit sich und beeinträchtigen oft die Komponierbarkeit.
    • Das größte Problem bei Web Components ist, dass sie nicht serverseitig-rendering-freundlich sind.
    • Ich weiß nicht, wie eine „HTML Web Component“ Zustandsänderungen behandeln soll.
      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.“

    • Das Schöne an Web Components ist, dass man eine Basisklasse finden oder bauen kann, die genau so funktioniert, wie man sie braucht.
      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...
    • Ich frage mich, ob du HTMX schon ausprobiert hast.
      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.
    • Im Grunde wird JSX durch eine nicht standardisierte benutzerdefinierte DSL ersetzt und das dann als Sieg verkauft.
  • „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.

    • HTML Modules wurden verworfen und entfernt und durch reine JavaScript-Imports ersetzt.
      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 img in eine React-Komponente einwickelt, nimmt man img ja nicht seine Funktion weg, sondern fügt etwas obendrauf hinzu – also ein Enhancement
    Der 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

    • Dass jede Webarchitektur am Ende HTML-Elemente rendert, ist natürlich selbstverständlich, aber das war nicht der Punkt
      Der Punkt ist, dass der Ansatz „HTML Web Component“ im Gegensatz zu React nicht von JavaScript abhängt, um mit dem Rendering zu beginnen
    • Den zentralen Unterschied, den der Text meint, sehe ich ungefähr so
      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
    • React erschwert in manchen Fällen auch den Zugriff auf eingebaute Funktionen
      Wenn man zum Beispiel onchange einem Element zuweist, liefert React nicht das change-Event, sondern eher etwas wie ein input-Event
      Tatsächlich ist es keines von beiden, sondern ein synthetisches Event, das näher an input als an change liegt
      Wenn man wirklich change möchte, muss man eine Element-Referenz verwenden und den Handler in einem Effekt direkt anhängen
    • Es hängt von der App-Architektur ab
      Wenn man mit React HTML vom Server zurückgibt, dann ist das Einwickeln von img in eine React-Komponente tatsächlich ein Enhancement des vorhandenen Elements
      Wenn aber alles clientseitig gerendert wird, lässt sich dieses img am Ende nicht von der React-Komponente trennen
    • Beim Lesen dieser Stelle musste ich an die umgekehrte Richtung denken, also React in anderes HTML einzubetten
      Meiner 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.js exportierten Klasse ein und erhält einen HTML5-Videoplayer zum Kopieren und Einfügen, der Torrents abspielt
    Wenn möglich, empfehle ich außerdem sehr, bestehende HTML-Elemente nachzuahmen
    Zum Beispiel habe ich src verwendet, weil video es 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ören
    Im 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