Svelte 5 Runes und SolidJS Signals: UI-Updates ohne erneutes Rendern
Sehen Sie, wie Svelte 5 Runes kompiliert und SolidJS Signale verbindet, um den DOM direkt zu aktualisieren, wie sich das von React und Angular unterscheidet – und wann ein Wechsel sinnvoll ist.
Jeder React-Entwickler muss irgendwann erklären, warum eine Komponente viermal gerendert wird, obwohl sich nichts Sichtbares geändert hat, und warum die Lösung memo, ein Abhängigkeitsarray sowie einen stabilen Callback beinhaltet. Svelte und SolidJS gehen von einer anderen Voraussetzung aus: Wenn das Framework genau weiß, welcher Zustandteil welchen DOM-Node versorgt, kann es diesen einen Node aktualisieren und den Neustart der Komponenten ganz vermeiden. Dieser Artikel erläutert, wie jede dieser Frameworks das erreicht, wie der Code in der Praxis aussieht, wo sich ihr Modell von React und Angular unterscheidet sowie wie man entscheiden kann, ob eines davon in seinem nächsten Projekt verwendet werden sollte.
Der virtuelle DOM war ein Mittel, kein Ziel
Die zentrale Idee von React bei seinem Erscheinen im Jahr 2013 war der virtuelle DOM. Die Benutzeroberfläche wird dabei als Funktion des Zustands beschrieben. Wenn sich der Zustand ändert, ruft React Ihre Komponente erneut auf, erstellt einen neuen In-Memory-Baum, vergleicht ihn mit dem vorherigen und wendet nur die Unterschiede auf den echten DOM an.
Dieses Design machte die Benutzeroberflächen weitaus vorhersehbarer als manuelle DOM-Manipulationen, und es bleibt weiterhin ein solides Modell. Es hat jedoch auch einen Nachteil: Die Komponentenfunktion wird erneut ausgeführt, unabhängig davon, ob sich deren Ausgabe ändern muss; ein neuer Baum wird allokiert und eine Differenzierungsschleife ermittelt, was tatsächlich geändert wurde – all das nur, um im schlimmsten Fall einen einzigen <span> zu aktualisieren. Wenn Sie Details darüber erfahren möchten, was der Reconciler vergleicht und warum, behandelt der Artikel „Wie die Differenzierung im virtuellen DOM funktioniert“ dieses Thema.
Ein Großteil der API von React seitdem – memo, useMemo, useCallback sowie kürzlich der React Compiler – dient dazu, die Arbeiten zu umgehen, die das Render-und-Diff-Modell sonst ausführen würde. Der Compiler automatisiert die Memoisierung, sodass Entwickler weniger davon manuell schreiben müssen, doch das zugrunde liegende Modell bleibt unverändert: Komponenten werden erneut ausgeführt, und Optimierung bedeutet, sie davon abzuhalten. Der Artikel zu was der React Compiler optimiert und was er Ihnen überlässt geht auf diese Grenzen ein.
Svelte und Solid stellen eine einfachere Frage: Was wäre, wenn die Abhängigkeit zwischen jedem Zustandswert und jedem DOM-Node genau bekannt wäre, sodass nur dieser Node bei einem Zustandswechsel beeinflusst wird?
Svelte: Ein Compiler, der den Aktualisierungscode für Sie schreibt
Svelte ist im Wesentlichen ein Compiler. Sie erstellen Komponenten in .svelte-Dateien, und beim Kompilieren wandelt Svelte sie in reines JavaScript um, das den DOM direkt manipuliert. Es gibt keinen virtuellen DOM und keine Laufzeit-Vergleiche, und nur eine kleine Laufzeitumgebung wird an den Browser gesendet.
Seit Svelte 5 wird Reaktivität durch Runes ausgedrückt – explizite Primitive, die der Compiler erkennt. Die untenstehende Komponente deklariert einen Zustand sowie einen daraus abgeleiteten Wert und rendernt beides in einem Button:
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>
{count} doubled is {doubled}
</button>
Das ist der gesamte Komponenteninhalt. Es gibt weder eine Setter-Funktion noch ein Abhängigkeitsarray. Man erhöht count wie eine gewöhnliche Variable, und da der Compiler bereits analysiert hat, welche Teile des Codes count und doubled lesen, erzeugt er Code, der genau diese Textknoten aktualisiert. $derived wird nur dann neu berechnet, wenn sich etwas ändert, was er liest. Beachten Sie, dass Event-Handler in Svelte 5 reguläre Attribute wie onclick sind, die die ältere Direktivsyntax on:click ersetzen.
Warum Teams es mögen
- Ohne Hooks, Setter oder Wrapper-Komponenten sind Svelte-Komponenten in der Regel deutlich kürzer als ihre React-Äquivalente. Weniger Code bedeutet in der Regel weniger Stellen für Fehler und schnellere Überprüfungen.
className, wodurch die Dateien für Designer und Reviewer, die nicht in React programmieren, leicht zugänglich sind.Für vollständige Anwendungen fügt SvelteKit Routing, Server-Rendering und API-Endpunkte hinzu und übernimmt damit die Rolle von Next.js für React – mit dem Ruf, eine einfachere Konfiguration zu erfordern.
Eine Einschränkung, die man bereits im Voraus kennen sollte: Runen sind Compilerfunktionen, daher funktionieren sie nur innerhalb von .svelte-Dateien sowie in Modulen mit der Endung .svelte.js oder .svelte.ts. Die Verlegung reaktiver Logik in eine einfache .js-Hilfsdatei funktioniert ohne diese Namenskonvention nicht.
SolidJS: JSX, das nur einmal ausgeführt wird
Solid lässt sich auf den ersten Blick leicht mit React verwechseln. Es verwendet JSX, es kombiniert kleine Funktionen, und ein Zähler sieht fast identisch aus:
function Counter() {
const [count, setCount] = createSignal(0);
return (
<button onClick={() => setCount(count() + 1)}>
Count: {count()}
</button>
);
}
Was React-Entwickler überrascht, ist die Tatsache, dass Counter genau einmal ausgeführt wird. Solid basiert hingegen auf fein abgestimmter Reaktivität mittels Signalen. createSignal gibt einen Getter und einen Setter zurück, wobei der Getter count() eine Funktionsaufruf ist und keine einfache Wert. Wenn JSX count() innerhalb einer Expression liest, protokolliert Solid, dass dieser spezielle Textknoten von diesem Signal abhängt. Der spätere Aufruf von setCount aktualisiert lediglich diesen Textknoten und nichts anderes. Die Komponentenfunktion diente lediglich als Einrichtungsschritt, um Signale mit DOM-Elementen zu verbinden; sie wird danach nicht mehr ausgeführt, sodass es nichts gibt, was neu gerendert werden müsste.
Dieses Modell ist der Grund dafür, dass Solid in gängigen Framework-Benchmarks auf dem oberen Niveau abschneidet – oft nahe an handgeschriebenem, reinem JavaScript. Betrachten Sie jede Benchmark-Rangliste lediglich als Momentaufnahme und messen Sie Ihre eigenen Arbeitslasten, doch der architektonische Vorteil ist real: Aktualisierungen kosten in etwa proportional zu den Änderungen, nicht zur Größe des Komponentenbaums.
Warum Teams es mögen
- Kein Konzept der erneuten Darstellung. Die Frage nach dem Grund für eine erneute Darstellung in React tritt nicht auf.
useMemo,useCallbackundReact.memohaben keinen Gegenpart, weil es nichts gibt, was übersprungen werden könnte.
Die Gewohnheiten, die man ablegen muss
Das einmal ausführende Modell hat Folgen, die Anfänger in Verwirrung bringen. Das Auseinandernehmen von Props am Anfang einer Komponente liest deren Werte nur einmal und stört die Reaktivität, weshalb Props in der Regel über props.name aufgerufen werden. Frühzeitige Rückgänge sowie Ternäre im Funktionskörper werden nur einmal ausgewertet, weshalb Solid Kontrollflusskomponenten wie Show und For bereitstellt. Sobald diese Regeln verstanden sind, sind sie konsistent – doch sie stellen die Hauptursache für Fehler bei Entwicklern dar, die aus React kommen.
Vergleich mit React und Angular
Der tiefere Unterschied ist eher philosophischer als syntaktischer.
React hat sein Kernmodell „erneut ausgeführt und verglichen“ und hat jahrelang Tools hinzugefügt, um die Kosten dieses Modells zu senken. Es bleibt weiterhin eine hervorragende Wahl: Sein Ökosystem ist unübertroffen, die Rekrutierung verläuft reibungslos und der React Compiler verringert tatsächlich die manuelle Memoisierung. Der Kompromiss besteht darin, dass man innerhalb eines Modells arbeitet, das an die Beschränkungen seiner Entstehungszeit angepasst ist.
Angular ist die vollausgestattete Unternehmenslösung mit Dependency Injection, RxJS sowie klaren Konventionen für nahezu alles. Es bewältigt sehr große Codebasen gut, doch die Komplexität und Lernkurve sind erheblich. Seine wichtigsten jüngsten Änderungen, wie Signals und zoneless Change Detection, bringen es in Richtung einer feingranularen Reaktivität, wie sie von Solid popularisiert wurde.
Diese Entwicklung ist in der gesamten Branche zu beobachten. Angular hat Signals übernommen, React führte einen Compiler zur Kompilierung zu Build-Zeiten ein, neuere Frameworks wie Qwik basieren auf fein abgestimmter Reaktivität, und Vue, dessen reaktive References stets den Signals nahekamen, erforscht mittlerweile eigene Kompilierungsstrategien. Es wäre übertrieben zu behaupten, Svelte und Solid hätten jede dieser Ideen erfunden, doch sie zeigten früh und deutlich, dass Kompilierung und Signals ein ganzes Framework tragen können.
Warum Entwickler weiterhin in diese Richtung gehen
Drei weniger spektakuläre Gründe erklären den größten Teil des Interesses:
- Weniger Frameworks, die man im Kopf behalten muss. Die Aufmerksamkeit richtet sich auf das Produkt statt auf die Update-Semantik des Frameworks. Die korrekte Memoisierung einer Callback-Funktion gilt bei niemandem als sinnvolle Aufgabe.
Sollten Sie wechseln?
Für ein bereits existierendes Produkt fast sicher nicht sofort. Wenn eine umfangreiche Anwendung bereits unter React oder Angular läuft und das Team diese Technologien gut kennt, ist eine Neuimplementierung einer der zuverlässigsten Wege, ein Projekt aufzuhalten. Auch die Größe des Ökosystems spielt eine Rolle: React bietet Bibliotheken für nahezu jeden Bedarf, und obwohl die Ökosysteme von Svelte und Solid lebendig sind und wachsen, sind sie kleiner. Prüfen Sie daher frühzeitig, ob die von Ihnen benötigten Komponentenbibliotheken, Formularwerkzeuge sowie Authentifizierungsintegrationen vorhanden sind und gewartet werden.
Bei neuen Projekten ändert sich die Rechnung. Ein Greenfield-Projekt, ein leistungsintensives Widget oder ein internes Tool sind geeignete Kandidaten mit geringem Risiko, um dies auszuprobieren:
- wählen Sie Svelte, wenn Sie eine besonders einfache Lernkurve sowie eine Funktionalität wünschen, die im Großen und Ganzen problemlos funktioniert
Kernpunkte
- Reacts Render-und-Diff-Modell ist vorhersehbar, doch die Ausführungszeit steigt proportional zum Komponentenbaum; Memoisierung und der React Compiler verringern diese Arbeit, ohne das Modell zu verändern.
- Svelte 5 bringt die Reaktivität durch Runes wie
$stateund$derivedin den Compiler, wodurch direkte DOM-Änderungen erzeugt und eine kleine Laufzeitbibliothek bereitgestellt wird. - Solid führt jede Komponente nur einmal aus und bindet Signale direkt an DOM-Node, wodurch erneute Renderungen vermieden werden – doch dies erfordert neue Gewohnheiten bei Props und Kontrollfluss.
- Das umfassendere Ökosystem bewegt sich in Richtung derselben Konzepte: Analyse zur Kompilierzeit, Signale anstelle erneuter Darstellungen sowie direkte Aktualisierungen statt Vergleichen.
- Nehmen Sie diese Frameworks an, wo ihre Stärken relevant sind und das Ökosystem Ihre Anforderungen abdeckt; schreiben Sie keine gesunde Codebasis um, nur um dem Trend zu folgen.