- Um die interaktive Demo eines CRDT-Tutorials als langlebigen Content zu behandeln, eignen sich Web Components, die sich direkt in HTML einbetten lassen, besser als ein bestimmtes Framework
- Die MDX-Komponenten von Astro bieten Komfort wie Build, CSS-Scoping und TypeScript, aber außerhalb von Astro kann beim Umzug ein Neuschreibungsaufwand entstehen
- Mit Web Components lassen sich Custom Tags wie
<pixelart-demo></pixelart-demo> in Markdown einfügen, und allein durch das Laden eines Skripts ist tagbasierte Wiederverwendung überall auf der Seite möglich
- Frameworks und auch TypeScript sind Abhängigkeiten, daher summieren sich Änderungen bei Versionen, APIs und Kompatibilität, und lange unberührter Code ist mit mehr Abhängigkeiten schwerer wiederherzustellen
- Die Webplattform ist so stabil, dass alte Websites auch in modernen Browsern funktionieren; für Arbeiten, die in 5, 10 oder 20 Jahren noch zugänglich sein sollen, ist ein standardbasierter Ansatz im Vorteil
Interaktive Demos wie Content bewahren
- Für eine CRDT-Blogserie wurden interaktive Demos benötigt, um Konzepte zu zeigen; als Beispiel diente ein kollaborativer Pixel-Art-Editor
- Maßgeblich für die Technologiewahl war, dass die Demo zwar aus HTML, CSS und JS besteht, aber eher Content ist, der in einen Blogbeitrag eingebettet wird
- Eher vergleichbar mit etwas, das wie ein Bild oder Video in den Text eingefügt wird
- Sie sollte überallhin mitgenommen werden können, wo HTML gerendert werden kann
- Die Website wurde Stand 2023 mit Astro erstellt, zuvor lief sie jedoch über einen eigenen Static Site Generator, Hugo, ein benutzerdefiniertes PHP-CMS, Tumblr, Movable Type und WordPress
- Auch wenn Astro aktuell gefällt, ist schwer anzunehmen, dass die Website für immer auf Astro laufen wird
Wie Markdown Migrationskosten senkt
- Ein Grund, warum die jüngste Migration einfach war, ist, dass der Content als Markdown-Textdateien erhalten blieb
- Dadurch reduziert sich typische Arbeit beim Umzug eines Systems
- Aus einem System exportieren und in ein anderes importieren
- Kompatibilitätsprobleme beheben
- Elemente entfernen, für die sich kein Migrationsweg finden lässt
- Legt man die Markdown-Dateien in eine neue Website, funktioniert das meiste unverändert
- In Markdown kann man direkt HTML schreiben; wenn sich also auch komplexe interaktive Diagramme als normale HTML-Tags ausdrücken lassen, sind sie genauso portabel wie der restliche Content
Der Komfort von Astro MDX und seine Grenzen bei der Portabilität
- Die MDX-Integration von Astro ermöglicht es, Astro-Komponenten innerhalb von Markdown zu rendern
- Astro-Komponenten nutzen zahlreiche Komfortfunktionen des Build-Systems
- HTML, CSS und JS in einer Datei schreiben
- Scoping von CSS-Selektoren
- TypeScript kompilieren
- Bedingtes Rendern von Markup
- Weitere Optimierungen
- Das Problem ist, dass all dieser Komfort nur innerhalb von Astro zuverlässig funktioniert
- Bei einem Wechsel zu einem anderen Site Generator müssen die Komponenten möglicherweise neu geschrieben werden
- HTML, CSS und JS müssen eventuell getrennt werden
- Möglicherweise ist eine neue Build-System-Konfiguration nötig
- Eventuell muss eine neue Methode für Style-Scoping gefunden werden
- Deshalb sind Astro-spezifische Funktionen zwar bequem, aber keine gute Wahl für Demos, die langfristig erhalten bleiben sollen
Was Web Components lösen
- Web Components sind ein Bündel standardisierter Webtechnologien, mit denen sich wiederverwendbare HTML-Elemente erstellen lassen
- Verwendet werden sie, indem man eine Klasse für ein benutzerdefiniertes Element schreibt, einen Tag-Namen registriert und diesen Tag dann im Markup nutzt
- Die Pixel-Art-Demo wird eingebettet, indem in Markdown einfach folgendes HTML steht
<pixelart-demo></pixelart-demo>
- Es ist keine besondere Konfiguration nötig und auch kein Ablauf, bei dem zuerst bestimmte Elemente platziert und danach Funktionen aufgerufen werden
- Die JS-Datei muss weiter gepflegt und per
<script>-Tag eingebunden werden, aber dass textueller Content auf Medien verweist, ist hier nicht anders als bei anderen Medien
- Sobald das Skript geladen ist, wird der Tag-Name registriert, und das funktioniert überall auf der Seite, auch wenn das Markup schon vor der JavaScript-Ausführung vorhanden war
Single-File-Aufbau und Shadow DOM
- Web Components können HTML, CSS und JS in einer einzigen Datei kapseln, ganz ohne separates Build-System
- Wenn der Code einer Komponente an einem Ort zusammenliegt, sinkt die mentale Last; Single-File-Komponenten haben auch Vorteile für die Developer Experience
- Die beispielhafte Komponente
<pixelart-demo> erbt von HTMLElement, hängt per attachShadow({ mode: "closed" }) ein Shadow DOM an und rendert darin internes Markup und Styles
- Das
import PixelEditor from "./PixelEditor.js"; am Dateianfang ist ein ES module import und hängt daher nicht von einem separaten Build-System ab
- Wenn die zugehörigen Dateien zusammen erhalten bleiben, verarbeitet der Browser die Module
- Shadow DOM isoliert die Komponente von der umgebenden Seite
- Wenn Styles mit der gesamten App geteilt werden sollen, kann das unhandlich sein
- Wenn vollständige Isolation gewünscht ist, passt es gut
- Wie bei Bildern oder Videos bleiben Aussehen und Verhalten überall gleich, egal wo die Komponente eingesetzt wird
Externe Konfiguration über Attribute
- Web Components können Attribute bereitstellen, über die sie von außen konfiguriert werden
- Attribute lassen sich wie native Attribute verwenden
- CSS-Variablen gehören zu den wenigen Werten, die in ein Shadow DOM hineinreichen können; im Beispiel setzt der Range-Slider daher so die Akzentfarbe
<range-slider style="--accent: #0085F2"></range-slider>
- Die Pixel-Art-Demo stellt über Attribute die Auflösung auf 20 um und zeigt Debug-Informationen für jedes Pixel an
<pixelart-demo debug resolution="20"></pixelart-demo>
- Aufrufe von
getAttribute und hasAttribute in der Komponentenklasse werden verwendet, um solche Attributwerte auszulesen
- Das war nützlich, um dieselbe Komponente in mehreren Schritten des Tutorials wiederzuverwenden und je nach Fortschritt bestimmte Funktionen einzuschalten
Frameworks und auch TypeScript sind Abhängigkeiten
- Es gibt Werkzeuge wie Lit, Stencil und Svelte, die zu Web Components kompilieren, aber Frameworks sind letztlich Abhängigkeiten
- Der hier größte befürchtete Trade-off sind langfristige Wartungskosten
- Auch TypeScript ist nicht Teil der nativen Grundlage des Webs und damit eine Abhängigkeit
- In den letzten 15 TypeScript-Versionen gab es breaking changes; viele davon brachten nützliche neue Funktionen, erforderten aber Codeanpassungen
- Wer Abhängigkeiten nutzt, muss mit neuen Releases, API-Änderungen und dem Aufwand für Kompatibilitätsprüfungen rechnen
- Da an diesem Code nicht dauerhaft weitergearbeitet werden soll, möchte man nicht irgendwann gezwungen sein, mehrere Jahre an Updates auf einmal abzuarbeiten
Erfahrungen beim Wiederherstellen alter Websites und die Stabilität der Webplattform
- Beim Aufbau eines Online-Museums wurde alter Code wiederhergestellt, der auf einem Laptop lag, der 10 Jahre lang nicht eingeschaltet war, und dabei zeigte sich: Je abhängiger eine Website ist, desto schwerer lässt sie sich wiederbeleben
- In rund 20 Jahren Webentwicklung konnte man Geburt, Aufstieg und Niedergang von jQuery beobachten und auch die Entstehung von Node.js sowie den io.js-Fork und die spätere Zusammenführung miterleben
- Backbone wurde schnell von AngularJS verdrängt, AngularJS wiederum von React, und auch React hat in etwa der halben Zeit mehrere verschiedene Arten erlebt, Komponenten zu schreiben
- Während sich das Ökosystem veränderte, wurde die Webplattform selbst vorsichtig weiterentwickelt, um bestehende Websites nicht zu beschädigen, und blieb dadurch bemerkenswert stabil
- Selbst alte Websites funktionieren noch in modernen Browsern
- Wer möchte, dass Arbeiten auch in 5, 10 oder 20 Jahren noch zugänglich sind, sollte unkontrollierbare Abhängigkeiten reduzieren und sich eher an Webstandards halten, die mit höherer Wahrscheinlichkeit nicht brechen
- Das Web hat seine Schwächen, aber wenn man mit seinen Eigenschaften direkt arbeitet statt über Zwischenschichten, wird es zu einer robusten, portablen und zukunftsfähigen Computing-Plattform
1 Kommentare
Meinungen auf Hacker News
htmx ist kein Framework, sondern eine Library, und da es im Artikel erwähnt wurde, möchte ich auf ein paar Punkte eingehen.
Zunächst behandelt der Artikel nicht das Problem, Server und Zustand zu synchronisieren; htmx konzentriert sich durch Hypermedia-Austausch genau darauf. Aus dieser Perspektive stehen htmx und Web Components also orthogonal zueinander.
Abhängigkeiten bringen neue Versionen, API-Änderungen und Kosten für die Aufrechterhaltung der Kompatibilität mit sich. Deshalb hat htmx keine Abhängigkeiten und konzentriert sich stark auf Abwärtskompatibilität. Es ist zum Beispiel mit IE11 kompatibel, und intercooler.js, gewissermaßen htmx 1.0, erschien 2013 mit einer einzigen jQuery-Abhängigkeit und wird immer noch unterstützt.
Viele JavaScript-Librarys haben eine Kultur von API-Neuschreibungen und schwierigen Upgrades, aber htmx ist ausdrücklich nicht so und sollte nicht in solche Verallgemeinerungen hineingezogen werden. Die einzige Breaking Change in htmx 2.0 dürfte vermutlich das Ende der IE-Unterstützung sein.
Ob Web Components länger Bestand haben werden als htmx, ist wohl wahrscheinlich, da sie Teil des Browsers sind. Aber soweit möglich wird htmx auch künftig sehr stabil bleiben und sich nur wenig verändern. Die API geht im Grunde in die richtige Richtung, und ich denke nicht, dass man aus Gründen der Reinheit oder Coolness alles neu schreiben muss.
Vor allem beantwortet htmx eine andere Frage als Web Components: Wie synchronisiert man Server und Zustand?
Mit WebComponent kann man sich in den Lebenszyklus von DOM-Elementen einklinken, die von außen verändert werden, etwa wie bei morphdom in Htmx. Wenn sich Attribute ändern, muss man die React-Komponente darüber informieren, und wenn ein Node aus dem DOM entfernt wird, muss man React mitteilen, dass es seine Aufräumroutinen ausführen soll. Ohne WebComponents wäre das meiner Ansicht nach schwer sauber und effizient umzusetzen gewesen.
Dadurch können wir weiterhin beim Htmx-Ansatz bleiben: Der Zustand der Business-Logik liegt vollständig auf dem Server, und auf dem Client bleibt nur ein kleiner, konservativer Teil, etwa das aktuell fokussierte Element oder gerade eingegebener Text. Je weiter man in diese Richtung geht, desto weniger Bugs und Race Conditions gibt es und desto besser wird die User Experience, sodass sich der Aufwand lohnt.
https://x.com/jlazaroff/status/1717176726248108469
https://htmx.org/essays/hypermedia-friendly-scripting/
Die Einschränkung, dass nur Formulare POST ausführen können und dass die einzige Art, eine Antwort zu verarbeiten, darin besteht, die gesamte Seite neu zu schreiben, wirkt willkürlich begrenzend. Wenn htmx so etwas wie HTML6 würde, würde es alle JavaScript-Frameworks überdauern.
Als Engineer, der sich hauptsächlich auf Backend konzentriert, bringen die meisten JS-Librarys, die ich einsetze, später einen hohen Wartungsaufwand mit sich und haben häufig größere API-Änderungen. Ich denke darüber nach, htmx einmal in einem persönlichen Projekt auszuprobieren.
Auch die Templates, die serverseitig HTML-Fragmente erzeugen, dürften dadurch weniger komplex werden.
htmx selbst ist ein wirklich überzeugendes Konzept, aber ich wünschte, es gäbe eine größere Community. Es ist zwar ein Henne-Ei-Problem, aber im Vergleich zu anderen Web-Frameworks gibt es nicht viele Ressourcen wie Blogposts oder Videos. Selbst grundlegende Dinge, etwa die Integration von Auth0-Authentifizierung in eine htmx-App, sind schwer zu finden.
non.io wurde vollständig mit reinem Web Components geschrieben und ist eine komplette SPA. Beim Überschreiten einfacher verschachtelter Blog-Komponenten habe ich einiges gelernt.
Für State Management gibt es weiterhin keine richtige Antwort. Wenn man kein Wrapper-Framework verwendet, muss man vieles selbst machen. Einer der guten Punkte an React ist, dass State Management weitgehend gelöst ist und es etablierte Muster und Erwartungen gibt. Bei Web Components fühlt es sich wie der Wilde Westen an, und da man komplexe Objekte nicht wie bei JSX als Attribute übergeben kann, mischt man am Ende Attribute, Events und direkte Aufrufe von Klassenfunktionen.
Auch bei der Performance war der Gewinn nicht so groß wie erwartet. Bei kleinen atomaren Elementen, etwa Icons, übersteigen die Kosten für die Instanzerzeugung den Nutzen, wenn Hunderte davon auf einer Seite sind; deshalb habe ich sie wieder aus Web Components herausgenommen. Statische Elemente lohnen sich als Web Components nicht, selbst wenn sie die Lesbarkeit des Codes verbessern, was ziemlich enttäuschend war.
Trotzdem gibt es Punkte, die ich wirklich mag. Wie der Autor sagte, ist es sehr einfach, Komponenten einer neuen Seite hinzuzufügen, unabhängig vom verwendeten Framework. Wenn etwas als Web Components gebaut ist, kann man es wirklich überall einsetzen. Beim Erstellen von Begleit-Sites wie der API-Dokumentation von nonio war es angenehm, trotz anderem Stack einfach die gewünschten Komponenten auswählen und verwenden zu können. Wenn man eine Komponente einbetten muss, lädt man das JS, fügt HTML hinzu, und fertig.
Auch die Style-Kapselung des shadow root ist ziemlich gut. Mir gefällt, dass ich mir bei der Arbeit an einer Seite keine Sorgen machen muss, versehentlich die Styles irgendeiner Komponente kaputtzumachen. Man muss weniger raten und prüfen, ob man die Styles anderer Elemente überschreibt, und braucht auch weniger visuelle Diff-Test-Frameworks, um das abzusichern.
Die kleine Paketgröße ist ebenfalls ein Pluspunkt. Es gibt keine Library oder zusätzliche Loads, alles ist eingebaut. Da man die benötigten Komponenten leicht auswählen kann, ist es auch sehr einfach, die Paketgröße niedrig zu halten.
Die Source-Komponenten von nonio sind hier: https://github.com/jjcm/nonio-frontend/tree/master/component...
Auch beim State Management gibt es nichts, was einen daran hindert, eine beliebige State-Management-Lösung anzubinden. Wenn das Ziel minimale Abhängigkeiten sind, habe ich auch einige Lösungen gesehen, die das eingebaute Event-Modell des Browsers nutzen.
Abschließend halte ich es persönlich für eine ziemlich gewagte Idee, eine komplette App mit reinen Web Components zu schreiben. Mit Lit bekommt man für 5 KB eine deutlich bessere Developer Experience: https://lit.dev
Solche Frameworks erzielen Performance oft dadurch, dass sie DOM-Manipulationen über die gesamte Seite hinweg bündeln; mit Web Components geht das nicht.
Allein aus diesem Grund sehe ich Web Components fast als Sackgasse. Sie können nützlich sein, wenn man nur kleine Funktionsinseln braucht statt vollständig clientseitig gerenderter Seiten.
Ich habe ähnliche Performance-Grenzen gesehen, dachte aber immer, dass der shadow DOM schwergewichtig sei. Jetzt frage ich mich, ob die Instanzerzeugung selbst teuer ist.
Beim State Management hatte ich dasselbe Problem, und ich überlege, Ideen aus der Desktop-Entwicklung zu übernehmen: einen Message Bus auf Fenster-Ebene, den alle Komponenten abonnieren und filtern, während jede State-Änderung auf diesen Message Bus publiziert wird.
Ein Beispiel für die Übergabe komplexer Objekte als Properties findet sich hier bei zx-listeditor:
https://github.com/wisercoder/uibuilder/blob/master/WebCompo...
Die Web Component selbst ist hier:
https://github.com/wisercoder/uibuilder/blob/master/WebCompo...
Die kleine 500-Zeilen-Library, die das ermöglicht, ist hier:
https://github.com/wisercoder/uibuilder/#jsx-for-web-compone...
Das Grundmuster von LiveState lautet: „Events dispatchen und State abonnieren“. Events und State-Updates werden über eine WebSocket-Verbindung übertragen, und die Frontend- und Backend-Libraries sind dünne Schichten über Phoenix Channels.
Derzeit werden Event-Handler-Funktionen in Elixir geschrieben, aber es läuft Arbeit daran, sie in jeder Sprache schreiben zu können, die nach WebAssembly kompiliert wird.
Ich erwarte nicht, dass mein bevorzugtes JS-Framework immer dasselbe bleibt. Ich weiß, dass es eine kurze Lebensdauer hat, und das gefällt mir
Voranzukommen, Fortschritte zu machen und sich zu verbessern, ist der Grund, warum man React, Vue, Svelte usw. verwendet. Im Moment will ich nichts Statisches. Denn keines der derzeit nutzbaren Frameworks, einschließlich Web Components, löst die Probleme besonders elegant
Wenn die Behauptung lautet, dass mit Web Components gebaute Websites länger halten als solche, die mit JS-Frameworks gebaut wurden, würde ich gern darauf wetten. Ehrlich gesagt halte ich es für wahrscheinlicher, dass in den nächsten 20 Jahren ein Teil des Web-Components-Technologie-Stacks aus Chrome, Safari oder Firefox entfernt wird und dadurch Apps kaputtgehen, als dass eine vor 2 Jahren geschriebene React-16-App wegen Änderungen an JavaScript kaputtgeht
Wenn man alle Dependency-Versionen einer React-16-App vollständig einfriert, geht sie vielleicht nicht kaputt, aber das ist eher so, als würde man ein altes Programm in einer VM oder einem Emulator laufen lassen, statt „an einer React-16-App weiterarbeiten und weiter daran hacken zu können“
Eine sinnvollere Wette wäre: „Kann man an einer React-ZZZ-App weiterentwickeln vs. kann man an einer mit Web Components gebauten App weiterentwickeln?“
Wenn ich die Bedingungen so setzen würde, dass sie meiner Sichtweise zugutekommen und zugleich sinnvoller sind, dann wäre es: „Sind die Kosten, eine React-App zu aktualisieren, um N Jahre an Dependency-Updates aufzuholen, höher oder niedriger als bei einer Web-Components-App?“ Wenn man in die Web-Components-App nicht jede Menge seltsame Dependencies eingebaut hat, halte ich es für sehr wahrscheinlich, dass die Update-Kosten bei der React-App höher sind
Im Grunde wettet man darauf, dass Browser-Anbieter weniger Abwärtskompatibilität brechen als die Autoren von React
HTML Imports wurden zugunsten einer reinen JS-Lösung verworfen, und Firefox hatte sie bereits implementiert
Auch Custom Elements v0 wurde verworfen; Chrome hatte es implementiert, und YouTube wurde damals eilig damit neu geschrieben. Weil YouTube so lange für die Umstellung brauchte, musste man ungefähr 4 Jahre warten, bis die Implementierung entfernt werden konnte
Um den Code sicher zu halten, muss man Libraries aktualisieren. Alte Library-Versionen werden jedoch nicht mehr unterstützt, und bekannte Schwachstellen, die man nicht beheben kann, beginnen sich anzusammeln. Angreifer haben sehr wahrscheinlich Programme, die Websites mit bekannten Schwachstellen scannen und automatisiert angreifen
Umgekehrt können Libraries oder Plattformen, die wie Web Components großen Wert auf Abwärtskompatibilität legen, alten Code länger unterstützen und dabei die Sicherheit aufrechterhalten
Der Fokus verschiebt sich von der Technik hin zu Menschen
Wenn ich ein neues Projekt starte, schaue ich zuerst darauf, was die Menschen, die an diesem Projekt arbeiten werden, kennen. Wenn es im Frontend einen gemeinsamen Nenner oder Best Practices gibt, so wie derzeit React, dann nehme ich einfach das
Über solche technischen Entscheidungen mache ich mir keine großen Sorgen. Teamzusammensetzung, Arbeitsmarkt für Bewerber und die Technologie-Rankings auf StackOverflow beantworten solche Fragen nämlich leicht
Aber wenn alle so denken, werden wir für immer React verwenden, selbst wenn es bessere Antworten darauf gibt, wie man Software baut. Zu sagen, man nutze das, was populär ist, bedeutet, die Verbesserung des Tech-Stacks anderen zu überlassen, die gute technische Lösungen finden und populär machen
Anders gesagt liegt diese Strategie auf der Adoptionskurve eindeutig eher bei den mittleren bis späten Anwendern. Viele solcher Artikel und Diskussionen richten sich an frühere Anwender
Da man in Markdown HTML verwenden kann, gilt: Wenn sich auch aufwendige interaktive Diagramme mit normalen HTML-Tags ausdrücken lassen, sind sie genauso portabel wie der Rest von Markdown – genau dasselbe lässt sich auch mit MDX tun.
Die Technik Web Components selbst hilft dabei nicht. Worum es dem Autor geht, ist die Schnittstelle zwischen Markup und den Codefragmenten, die Runtime-Funktionalität anwenden. Web Components sind hier nur ein Implementierungsdetail. Es spielt keine Rolle, ob ein Name zwischen spitzen Klammern auf eine React-Komponente, etwas aus Astro oder eine Web Component verweist. Entscheidend ist, dass etwas anderes aufgerufen wird.
Der Nachteil von Web Components ist hier, dass sie praktisch nur auf dem Client laufen. Es gibt keine Möglichkeit, serverseitig gerenderte Inhalte des Shadow DOM an den Client zu übergeben; selbst wenn eine Web Component völlig nicht-interaktiv ist, braucht sie deshalb Client-JS zum Rendern. Bei anderen Frameworks ist das nicht so.
Das heißt nicht, dass der Punkt des Autors falsch ist. Als Methode, Schnittstellen zwischen Codefragmenten zu systematisieren, sind Web Components vielleicht die beste und langlebigste Lösung. Auf dem Server helfen Web Components jedoch überhaupt nicht. Sie werden nicht gerendert, die Schnittstelle ist umständlich, und der Code ist wahrscheinlich ohnehin so geschrieben, dass er als Ganzes verarbeitet werden kann. Wenn man auf dem Server Astro verwendet, sollte man einfach bei Astro bleiben. Dasselbe gilt für React, Vue oder was auch immer.
Web Components glänzen auf dem Client. Wenn man Drittanbieter-Komponenten verwendet, die möglicherweise nicht mit dem eigenen Framework geschrieben wurden, muss man nicht wissen, mit welchem Framework die Komponente auf der Seite gebaut wurde. Man setzt ein HTML-Tag ein, und es funktioniert. Der Schnittstellenmechanismus wandert auf Browser-Ebene, sodass zwei Frameworks die Implementierungsdetails des jeweils anderen nicht kennen müssen.
In dieser Hinsicht stimmt es, dass man irgendein Tool braucht. Dieses Tool kann aber einfach jede serverseitige Template-Engine sein, die das initiale HTML befüllt und bootstrapped.
Serverseitig gerendertes Shadow DOM kann man jedoch an den Client übergeben. Das nennt sich Declarative Shadow DOM und funktioniert in allen großen Browsern außer Firefox. Firefox arbeitet ebenfalls daran, und es gibt auch ein Polyfill.
https://developer.chrome.com/articles/declarative-shadow-dom...
Nebenbei: Dieses Polyfill ist ziemlich einfach, sodass man es möglicherweise auch dann verwenden kann, wenn der Browser es derzeit nicht unterstützt.
Wenn es auf dem Server renderbare Web Components gäbe, würde das viele Möglichkeiten eröffnen, die User Experience von Multi-Page-Apps zu verbessern.
Die JS-Welt ist immer noch zu sehr auf fette Clients fixiert, die die volle Kontrolle haben, und verpasst dadurch die interessanten Dinge, die in der Server-Welt passieren.
Lösungen wie Rails Hotwire, Phoenix LiveView und Laravel Livewire können 80 % des Frontends mit minimalem JS und nahezu ohne Komplexität in der Developer Experience abdecken.
Ich habe auch funktionsreiche Frontend-Apps gebaut, die ohne Server Datenbanken und Object Storage lesen und beschreiben. Sie sind sehr portabel, und die Installation besteht lediglich darin, ein paar Dateien hochzuladen. Sie können direkt von einem einfachen CDN laufen und sind sehr schnell.
Die meisten Frontend-Entwickler, die ich kenne, kennen auch den Hotwire-Ansatz, aber für sie erhöht so ein Stack die Komplexität der Developer Experience. Manchmal sagen Leute „Komplexität“, meinen aber eigentlich „Unvertrautheit“. Frontend und Backend können beide übermäßig komplex werden, müssen es aber nicht.
Wenn etwas schiefgeht, ist es meiner Ansicht nach besser, mehr Kontrolle zu haben. Besonders in schnellen Umgebungen, in denen der Kunde sofort etwas verlangt.
Persönlich schreibe ich lieber alles in JavaScript/TypeScript, statt Syntax Sugar über HTML zu streuen.
Nur weil man es wie bei Livewire auf die Serverseite verlagert, verschwinden starke Nachteile wie Latenz nicht.
Der Titel stimmt wahrscheinlich, aber ich bin mir nicht sicher, ob das wichtig ist. Die meisten Anwendungen leben nicht so lange.
Ich habe kürzlich Web Components ausprobiert, und Funktionen, die in jedem Framework sehr simpel sind, waren wirklich verwirrend und kompliziert einzurichten. Wenn die Komponente einfach ist, mag das egal sein, aber wenn man eine Anwendung mit JS baut, sind Slots eine Kernfunktion, weil sie zusammensetzbare Komponenten ermöglichen.
Auch das Debuggen des Shadow DOM in den Developer Tools war wirklich verwirrend.
Reacts renderProp oder Vues scoped slot werden sehr häufig verwendet, um Daten von einer Parent-Komponente in eine Child-Komponente einzuspeisen. Ein solches Verhalten in einer Web Component nachzubilden, ist ohne MutationObserver-Hacks aber praktisch unmöglich. Die Annahme von Web Components, dass Child- und Parent-Komponenten die Informationen des jeweils anderen nicht kennen müssen, passt nicht zur realen Welt.
Auch die Annahme, dass eine Child-Komponente immer unabhängig vom Parent geladen und initialisiert wird, ist in den meisten Frameworks falsch. In den meisten Frameworks entscheidet die Parent-Komponente, ob sie das Child tatsächlich lädt oder initialisiert.
Web Components können zwar besser geeignet sein, um isolierte und wiederverwendbare Komponenten zu schreiben, aber die DOM API, mit der man alles Mögliche zusammensteckt, damit eine Anwendung funktioniert, ist einfach miserabel.
Man merkt ihr an, dass sie zum Bearbeiten von XML-Dokumenten gemacht wurde.
Es gibt noch einen weiteren Grund, warum ich selbst für isolierte, wiederverwendbare Komponenten keine Web Components erstelle: Kein Editor bekommt Dinge wie Autovervollständigung für Attribute oder Event-Namen oder Tippfehlerprüfung wirklich richtig hin.
Um sie nützlich zu machen, muss man mehrere Abhängigkeiten zusammenkleben, und diese Abhängigkeiten werden vermutlich nicht so gut gepflegt sein wie React.
Ich habe einmal in einem Unternehmen gearbeitet, das dieser Philosophie folgte. Jede UI-Komponente war ein Web Component mit einem eigenen npm-Paket, das man jeweils installieren musste. Es funktionierte zwar gut, aber es brachte keinerlei Vorteile. Sechs Jahre später gibt es immer noch keine Vorteile. Man optimiert damit wohl für eine Zukunft, die nie kommen wird.
HTML/CSS-Websites werden alles andere überdauern.
Denn Text, Bilder und Layout stecken tatsächlich in etwas Statischem, können unangetastet ewig weiterleben und erfordern weder die Ausführung komplexen Codes noch die Pflege vager, sich schnell ändernder Quasi-Standards.
Wenn man langlebige Websites bauen und langlebige Technologie haben möchte, sollte man lernen, progressiv erweiterte HTML-Websites zu erstellen. Der Ansatz, nutzlose undefinierte HTML-Elemente mit Bindestrich wie bei Web Components zu erzeugen und sie erst nach dem Ausführen einer Menge JavaScript zu definieren, oder JavaScript-Frameworks, die nicht einmal so tun, als würden sie HTML verwenden, wird nur ein paar Jahre halten.
Zumindest bis Browser die Unterstützung für HTTP/1.1 entfernen.