9 Punkte von GN⁺ 2025-02-19 | 7 Kommentare | Auf WhatsApp teilen
  • Zusammenfassung der Probleme, die nach dem Upgrade einer Webanwendung auf die aktuelle Version Svelte 5 aufgetreten sind
    • Unerwartetes Verhalten trat durch Deep Reactivity und den geänderten Lifecycle auf
  • Obwohl Svelte 3/4 lange sehr geschätzt wurde, wird Svelte künftig wohl nicht mehr für neue Projekte gewählt werden

Die Notwendigkeit von Geschwindigkeit

  • Das Svelte-Team versuchte mit Deep Reactivity eine Performance-Optimierung und erreichte dadurch bessere Leistung
  • Schon zuvor bot Svelte durch den Compile-Prozess hohe Geschwindigkeit, was eine besondere Stärke gegenüber anderen Frameworks war
  • Dadurch wurde das Framework zwar undurchsichtiger und das Debugging schwieriger, aber das erschien als vertretbarer Trade-off zwischen Performance und Produktivität

Die Notwendigkeit von Geschwindigkeit

  • Die zentrale Änderung, auf die sich das Svelte-Team in Svelte 5 konzentriert, ist „Deep Reactivity“, also der Versuch, die Performance durch feinere Reaktivität zu steigern
  • In früheren Svelte-Versionen wurde dieses Ziel vor allem mit dem Svelte-Compiler erreicht
    • Dass Entwickler dafür keine neuen Konzepte lernen mussten und interne Logik leicht umstrukturieren konnten, unterstrich die Eigenständigkeit von Svelte
  • Gleichzeitig machte dieser Compile-Prozess das Framework undurchsichtiger, was das Debugging komplexer Probleme erschwerte
    • Durch Bugs im Compiler selbst traten Fehler auf, deren Ursache schwer zu finden war, und manchmal ließ sich das Problem nur durch ein vollständiges Refactoring der betroffenen Komponente beheben
  • Trotzdem wirkte es weiterhin wie ein vernünftiger Trade-off in Bezug auf Geschwindigkeit und Produktivität, sodass sogar die Unannehmlichkeit in Kauf genommen wurde, Projekte regelmäßig zurückzusetzen

Svelte ist nicht JavaScript

  • Svelte 5 verdoppelt diesen Trade-off
  • Der entscheidende Unterschied ist, dass der Kompromiss zwischen Abstraktion und Performance nun über die Compile-Phase hinaus bis in den Runtime-Bereich hineinreicht
    • Einsatz von Proxys zur Unterstützung von Deep Reactivity
    • Impliziter Komponenten-Lifecycle-Status
  • Diese beiden Änderungen verbessern die Performance und lassen die Entwickler-API eleganter erscheinen
  • Was sollte daran schlecht sein? Leider sind diese beiden Funktionen ein typisches Beispiel für eine leaky abstraction
    • Am Ende entsteht für Entwickler eine komplexere Umgebung

Proxys sind keine Objekte

  • Durch den Einsatz von Proxys konnte das Svelte-Team die Framework-Performance etwas weiter steigern, ohne zusätzliche Arbeit von Entwicklern zu verlangen
    • In Frameworks wie React führen Zustände, die über mehrere Komponenten hinweg weitergereicht werden, leicht zu unnötigen Re-Renderings; Svelte führte Proxys ein, um das zu verringern
    • Der Svelte-Compiler vermied bereits zuvor einige Probleme, die beim Vergleich eines Virtual DOM auftreten können, doch offenbar wurde angenommen, dass sich die Performance mit Proxys weiter verbessern lässt
    • Das Svelte-Team erklärte außerdem, Proxys würden auch die Developer Experience verbessern, und vertrat die Ansicht, dass sich damit „sowohl Effizienz als auch Benutzerfreundlichkeit maximieren“ ließen
  • Das Problem ist, dass Svelte 5 oberflächlich einfacher wirkt, in Wirklichkeit aber mehr Abstraktion hinzufügt
    • Wenn zum Beispiel ein Proxy zur Erkennung von Array-Methoden verwendet wird, entfällt der Vorteil, in Svelte 4 Code wie value = value schreiben zu müssen
    • In Svelte 4 mussten Entwickler die Funktionsweise des Compilers in gewissem Maß verstehen, um Reaktivität auszulösen. Svelte 5 vermittelt dagegen den Eindruck, man könne „den Compiler vergessen“, doch in der Praxis stimmt das nicht
    • Mit der neuen Abstraktion kommt zwar mehr Bequemlichkeit, zugleich steigen aber auch die Regeln, die Entwickler kennen müssen, damit der Compiler wie gewünscht arbeitet
  • Nach langer Nutzung von Svelte wurden persönlich mit der Zeit häufiger Svelte-Stores und seltener reaktive Deklarationen verwendet
    • Svelte-Stores liegen konzeptionell näher an grundlegendem JavaScript, der Aufruf der Methode update ist einfach, und die $-Syntax war eher ein zusätzlicher Vorteil
    • Wie reaktive Deklarationen erzeugen Proxys das Problem, dass „etwas wie eins aussieht, sich an den tatsächlichen Grenzen aber anders verhält“
  • Beim ersten Einsatz von Svelte 5 schien alles gut zu funktionieren, doch beim Versuch, Proxy-Status in IndexedDB zu speichern, trat ein DataCloneError auf
    • Noch dazu muss man, um sicher festzustellen, welche Werte Proxys sind, strukturierte Klone mit try/catch ausprobieren, was Performance kostet
    • Letztlich muss man sich also merken, was ein Proxy ist, und in Kontexten, die Proxys von außen nicht erkennen, jedes Mal $state.snapshot verwenden
    • Das führt am Ende dazu, dass die ursprüngliche Absicht „Abstraktion erhöht die Entwicklerfreundlichkeit“ ins Gegenteil kippt und Entwicklern mehr komplexe Regeln und Abläufe abverlangt

Komponenten sind keine Funktionen

  • Der Grund, warum das Virtual DOM um 2013 populär wurde, war, dass sich Anwendungen als Kombinationen von Funktionen modellieren ließen
    • Svelte setzte statt auf ein Virtual DOM auf einen Compiler, um Lifecycle-Funktionen zu vereinfachen und die Performance zu steigern
    • In Svelte 5 wurde das Lifecycle-Konzept jedoch in einer Form wieder hinzugefügt, die React Hooks ähnelt
  • In React sind Hooks ein Abstraktionskonzept, das zustandsbezogenen Code in Lifecycle-Methoden reduziert
    • Der Code wird sauberer, aber es gibt viele Punkte, auf die Entwickler achten müssen, etwa wenn in setTimeout auf Status zugegriffen wird
    • Auch in Svelte 4 konnte es Probleme geben, wenn asynchroner Code beim Unmount einer Komponente noch auf DOM-Elemente zugriff
    • In Svelte 5 scheint nun impliziter Status zum Komponenten-Lifecycle hinzugekommen zu sein, um Zustandsänderungen und Effekte zu koordinieren
  • Die offizielle Dokumentation zu $effect beschreibt dies wie folgt:
    > „$effect kann überall platziert werden, muss aber während der Initialisierung einer Komponente (oder während ein übergeordneter Effekt aktiv ist) aufgerufen werden und verschwindet, wenn die Komponente (oder der übergeordnete Effekt) unmounted wird“
  • Das deutet darauf hin, dass es entgegen der Aussage, der Lifecycle bestehe nur aus den zwei Phasen Mount/Unmount, tatsächlich eine komplexe Effektstruktur gibt, in der Zustandsänderungen verfolgt werden müssen
  • In der offiziellen Lifecycle-Dokumentation heißt es zwar, es gebe kein „before update/after update“, doch gleichzeitig tauchen neue Konzepte wie $effect.pre und tick auf
  • Das bedeutet faktisch, dass man neben Mount/Unmount auch den Zeitpunkt von Zustandsänderungen verstehen muss
  • Das Problem im praktischen Einsatz war, dass selbst Status, der an eine mit Svelte nicht zusammenhängende Funktion übergeben wird, an den Komponenten-Lifecycle gebunden bleibt
  • Zum Beispiel wurde ein Muster verwendet, bei dem ein Modal-Fenster über einen Store verwaltet und ein Callback an eine Kindkomponente weitergegeben wird
    const { value } = $props()  
    const callback = () => console.log(value)  
    const openModal = () => pushModal(MyModal, { callback })  
    
  • Wenn sich dieser Code innerhalb der Modal-Komponente befindet, wird zuerst die aufrufende Komponente unmounted, und in diesem Moment ändert sich value zu undefined
  • In diesem Repository gibt es ein minimales Reproduktionsbeispiel
  • Das heißt: In einem Callback, der nach dem Ende des Komponenten-Lifecycles weiterlebt, werden zuvor referenzierte Props plötzlich zu undefined
  • Dieses Verhalten unterscheidet sich von normalem JavaScript und wirkt so, als würde Svelte selbst eine Art Garbage Collection durchführen
  • Dafür mag es technische Gründe geben, aber das Verhalten ist unerwartet und überraschend

Fazit

  • Einfachheit ist ohne Zweifel attraktiv, aber wie Rich Hickey sagte, easy bedeutet nicht automatisch simple
  • Wie Joel Spolsky mag ich unerwartetes Verhalten nicht
  • Svelte hat bisher viel „Magie“ gezeigt, aber in dieser Version muss man sich zu viel merken, um diese Magie zu nutzen, sodass die Belastung den Nutzen übersteigt
  • Der Punkt dieses Artikels ist nicht, das Svelte-Team anzugreifen; vielmehr ist bewusst, dass viele Menschen Svelte 5 (und React Hooks) bevorzugen
  • Entscheidend ist das Gleichgewicht zwischen Komfort für Nutzer und der Möglichkeit für Nutzer, die Kontrolle zu behalten
  • Wirklich gute Software basiert nicht auf „Cleverness“, sondern auf „Verständnis“
  • Mit dem Fortschritt von AI-Tools wird es wichtiger, Werkzeuge zu wählen, die vorhandene Erfahrung nutzen und tiefes Verständnis fördern, statt Tools, bei denen man nicht mehr weiß, was man eigentlich tut
  • Dank an Rich Harris und das Team für die bislang erfreuliche Entwicklererfahrung. Hoffentlich ist dieser Text kein unzutreffendes Feedback

7 Kommentare

 
firea32 2025-02-24

Proxys machen es für die Entwickler bequem, aber wer debuggen muss, wird dabei echt wütend, haha.

 
bichi 2025-02-21

Das Nebenprojekt hat bei solidjs die beste DX >_< / glücklich

 
pcj9024 2025-02-20

Ich denke, dass auch React/nextjs durch Alternativen wie Svelte stark herausgefordert werden konnte.
Im Kern ist Svelte eine language, daher hoffe ich, dass es auch gut die Richtung aufzeigt, in die sich eine Sprache zur Beschreibung von UI weiterentwickeln sollte.

Ich werde React verwenden.

 
iolothebard 2025-02-20

Zu viel des Guten
Besessenheit
Aufgesetzte Überkonstruktion

 
colus001 2025-02-20

Ich denke, dass sich Svelte 5 unter nicht geringem Einfluss von React und insbesondere Next auf seltsame Weise verändert hat. +page ist schwer zu verstehen, wenn man Svelte nicht kennt, und Runen wie $state oder $derived wirken, als würden sie React folgen; da erschien mir die Zeit, als man einfach $: vor Variablen setzte, fast besser. Auch die altmodische Syntax wie {#each a in array} {/each} ist zwar noch erträglich, aber weiterhin umständlich. Wenn es um Leistungsverbesserungen durch optionale Reaktivität geht, halte ich SolidJS für einen deutlich besseren Ansatz. Da es JSX unverändert verwendet, ist der Umstieg von React aus auch vergleichsweise leicht. Es ist fast erstaunlich, dass SolidJS verhältnismäßig so wenig Aufmerksamkeit bekommt.

 
xiniha 2025-02-19

Ich habe den Eindruck, dass Signals sich auf den Trough of disillusionment des Gartner hype cycle zubewegt 🤔 Mit der schrittweisen Etablierung von Use Cases könnte sich die Bewertung nach und nach verbessern.

 
GN⁺ 2025-02-19
Hacker-News-Kommentare
  • Anfangs fand ich runes nicht besonders interessant. Meine Meinung änderte sich jedoch, als ich externe reaktive Komponenten in .svelte-Templates importieren und die Reaktivität intern kapseln konnte. Das bedeutet, dass man vitest-Tests schreiben und dennoch die Vorteile der Reaktivität nutzen kann. Das ist wirklich mächtig und AFAIK einzigartig in der Frontend-Welt

    • Die meisten Frontend-Entwickler testen überhaupt nicht. TypeScript ist das Werkzeug, das Leute zur Sicherstellung der Korrektheit verwenden, und das aus gutem Grund. Svelte-Nutzer hatten jedoch schon immer einen engen Blick auf TypeScript, und auch dafür gibt es gute Gründe
    • Ich persönlich bevorzuge es, testbaren Frontend-Code zu schreiben, und Svelte 5 ist in dieser Hinsicht revolutionär. Im Browser reaktiv zu sein und dabei so gut wie Unit-Tests zu bleiben
    • Trotz all dem sagt der Blogpost die Wahrheit. Das Hinzufügen von Proxys fühlt sich sehr unangenehm an. React und Vue haben mich verloren, als sie begannen, Abstraktion auf Abstraktion zu stapeln, und Proxys waren der Ausgangspunkt dafür
    • Dass Svelte 5 kein JavaScript ist, ist <i>der Grund, warum ich Svelte 5 mag</i>
    • Ich denke, es gibt zwei wesentliche vernünftige Wege, Frontend/Web zu machen
        1. Statisches HTML oder serverseitig gerenderte Templates, vielleicht HTMX
        1. Eine Sprache/Plattform, die zu JavaScript kompiliert. Mindestens TypeScript, aber weil ich denke, dass HTML und CSS tatsächlich ziemlich gut sind, sind JSX, React, Tailwind usw. <i>ausgeschlossen</i>, und Svelte 5 sowie einige andere Frameworks sind tatsächlich eine Verbesserung gegenüber Vanilla-TypeScript
    • Svelte 5 ist der klare Sieger in Kategorie 2
    • Es hat großartige HTML-Templates, einfache und vernünftige Zustandsweitergabe und die Fähigkeit, modularen Code leicht zu schreiben. Es arbeitet gut mit CSS zusammen, man kann oft einfache Wegwerf-Apps und Tools in ein oder zwei Dateien bauen, und auch größere, ernsthafte Anwendungen sind möglich. Es ist weniger magisch und weniger überraschend als Svelte 4 und ehrlich gesagt angenehm zu benutzen. Zum Glück kümmere ich mich nicht um IndexedDB
    • Ich weiß heute absolut keinen Grund mehr, auch nur eine Zeile JavaScript zu schreiben, aber jedem das Seine
  • Ich entwickle aktiv eine kommerziell ausgerollte SvelteKit-Anwendung und möchte ein paar Gedanken zu dieser Erfahrung teilen

    • Was mich anfangs zu SvelteKit gezogen hat, war seine Einfachheit. Nach dem Aufsetzen des Projekts konnte ich Datei für Datei an modernem HTML/JS/CSS arbeiten und gleichzeitig die Vorteile eines modernen Frameworks ohne zusätzliche Komplexität nutzen. Das erinnerte mich an die frühen Tage der Webentwicklung, als alles lief, indem man einfach HTML-Dateien auf einen Apache-Server legte
    • Es ist jedoch enttäuschend zu sehen, wie Svelte sich von diesem einfachen Paradigma entfernt. Von Anfang an hat Rich Harris die einfache Nutzung und Schlichtheit von Svelte als zentrale Verkaufsargumente betont. Die aktuelle Version von SvelteKit ist nicht schlecht, aber ich habe die frühere Version bevorzugt. Damals musste man sich nicht mit Routing-Strukturen wie +page beschäftigen. Man konnte Svelte-Dateien dort ablegen, wo man wollte, und sie wurden nahtlos gerendert, während man weiterhin die Vorteile moderner Frameworks hatte
    • Diese Änderungen fügen Komplexität hinzu, die vorher nicht nötig war, und könnten Svelte von dem wegführen, was seinen Reiz ursprünglich ausgemacht hat. Ich habe mich auf Basis dessen entschieden, was ich bereits kannte
  • Es ist schade, dass EmberJS verschwunden ist. Die API war in den letzten 10 Jahren ziemlich stabil. Ironischerweise wird jemand, der in den letzten 10 Jahren EmberJS-Apps geschrieben hat, bei Migrationen vermutlich weniger Schwierigkeiten haben als jemand, der in derselben Zeit dasselbe mit React, Svelte, Vue usw. gemacht hat

    • Leider hat das Ember-Team anfangs einige seltsame Entscheidungen getroffen, und im Vergleich zu normalem JavaScript war es nicht leicht zu verstehen (das meiste davon wurde inzwischen behoben)
    • Ob etwas JavaScript ist oder nicht, ist im Vergleich zur Stabilität der API nicht besonders wichtig
    • Für mich persönlich ist das Problem von JavaScript, dass es sich zu oft verändert
  • Die beiden Github-Links, die der Autor oben im Beitrag aufführt, verweisen auf dasselbe Problem, und für dieses Problem gibt es eine Lösung (use $state.raw)

    • Ich bin seit Svelte 2 oder 3 ein Fan von Svelte. Es kam dem Schreiben von normalem HTML/CSS/JS am nächsten und bot dennoch die Vorteile eines Frameworks (und dazu Sass und TypeScript). Fantastisch
    • Svelte 5 fühlte sich wegen runes seltsam und beunruhigend an. Nachdem ich ein Projekt aktualisiert und an anderen Projekten gearbeitet habe, ist es gar nicht so schlecht. Svelte 5 erlaubt es nicht, die alte und die neue Art der Zustandsbehandlung zu mischen, und die Fehlermeldungen sind meist informativ
    • Ich sehe in diesem Thread Leute sagen, htmx und Vanilla-JS seien objektiv besser ... nein? Vielleicht für das, was ihr macht. Ich persönlich finde Svelte immer noch viel leichter zu verstehen als React. Für Leute, denen Benchmarks wichtig sind: Svelte ist so schnell wie SolidJS (React-Nutzer könnten wahrscheinlich leicht zu Solid wechseln, die Syntax fühlt sich ähnlich an)
  • Svelte 5 ist auf die <i>schlechteste</i> Weise kein JavaScript. Es behebt die Probleme von JS nicht, sondern liefert nur eine undichte Abstraktion für einige Frontend-Probleme. Ich denke, Solid geht in eine bessere Richtung als Svelte. Solid hängt nicht von einer neuen Sprache ab. Aber weil JS nicht ideal ist, gibt es den Impuls, etwas zu bauen, das nicht JS ist. Elm ist der Vorläufer von Svelte. Aber ich denke, wir können etwas Besseres machen ...[0]

  • Ich habe angefangen, Svelte 5 zu verwenden, weil ich Stores in Svelte 4 wirklich gehasst habe. Ich nutze SvelteKit und Svelte 5 für ein neues Projekt, und ich muss sagen ... Reacts Produktivität ist immer noch unschlagbar, obwohl SvelteKit und Svelte technisch besser sind

    • Ein paar Dinge, die wirklich genervt haben: Alle Seiten heißen +page.server.ts oder +page.svelte oder eine Variante davon, was es schwierig macht, Code leicht zu durchsuchen. Sveltes Tooling existiert getrennt von tsc und ESLint, wodurch es schwerer ist, es in CI zu integrieren und in der Entwicklung zu nutzen
    • Es gibt auch seltsame Probleme mit der Abwärtskompatibilität. Zum Beispiel verwenden die meisten Svelte-Pakete immer noch Stores, sodass man mit zwei Welten gleichzeitig kämpfen muss, was das Schreiben von Code manchmal wirklich verwirrend macht. Außerdem scheint Svelte HMR immer noch in einem frühen Stadium zu sein, sodass beim Neuladen von Svelte-Modulen der Zustand kaputtgehen kann
    • Ich möchte Svelte wirklich mögen. Es rendert ziemlich schnell, und mir gefallen die Ideen dahinter. Aber Reacts Produktivität ist unschlagbar
  • Zu sagen, Svelte sei kein JavaScript, nur wegen unerwartetem Verhalten beim Übergeben von Closures in Callbacks, wirkt seltsam. Ein besserer Titel wäre „Ich mag Svelte 5 nicht, weil es mich überrascht“

  • Wenn ihr eine Bibliothek sucht, mit der man Komponenten und Apps mit reinem JavaScript bauen kann, schaut euch Lit an: Lit

    • Es gibt ein zusätzliches Paket für Signals zur tiefen Reaktivität, mit dem Ziel der Integration in den kommenden Signals-TC39-Vorschlag: Signals
    • Lit wird in großen Apps wie Photoshop, Reddit, Home Assistant und dem Internet Archive eingesetzt
  • Wollt ihr ein vernünftiges Frontend-Erlebnis? Dann nutzt Vanilla JavaScript, Web Components, htmx und Blazor

    • JS-Frameworks sind aus irgendeinem Grund Wahnsinn