Svelte ist ein neues JavaScript-Frontend-Framework zum Entwickeln von Webseiten und Web Apps. Wer jetzt denkt “nicht noch eins”, der sollte kurz innehalten – Svelte sorgt momentan mächtig für Furore in der Frontend-Welt. Zum einen ist es ausdrucksstark: Minimaler Code führt zu maximalen Ergebnissen. Boilerplate-Code, um eine Komponente zu erstellen? Nicht vorhanden. Gleichzeitig ist es rasend schnell. Performance-Tuning durch den User mit Hilfe von Dingen wie shouldComponentUpdate? Nicht nötig. Darüber hinaus ist die Bundlesize im Vergleich zu anderen Frameworks verschwindend gering. Dennoch ist es sehr umfangreich. Ein Animationspaket und eine State-Management-Lösung sind bereits enthalten. Wie schafft Svelte das? Darauf wollen wir in diesem Artikel einen Blick werfen. Gemeinsam machen wir die ersten Schritte mit Svelte und bauen eine Bücherliste-App.

Zunächst ein kleiner Blick auf die Geschichte: Das UI-Framework ist schon fast vier Jahre alt. Ende 2016 wurde die erste Version auf GitHub veröffentlicht. Der Autor ist Richard Harris, der zu diesem Zeitpunkt für The Guardian arbeitete und mittlerweile sein Geld bei der New York Times verdient. Sein Tagesgeschäft ist das Erstellen von interaktiven Grafiken – und Svelte entstand in diesem Kontext. Harris wollte ein UI-Framework, das möglichst wenige Kilobytes in den Browser schaufelt – eine Nachrichtenwebseite ist auch so schwergewichtig genug. Zusätzlich sollte es schnell sein und flüssige Animationen ermöglichen. Zu guter Letzt sollten auch weniger erfahrene Redaktionskollegen es schnell erlernen können. Da keines der existierenden Frameworks seine Anforderungen erfüllte, entwickelte Harris Svelte. Version 1 erfüllte die ersten beiden Punkte – klein, schnell – bereits sehr gut. Doch erst mit Version 3, die im April 2019 veröffentlicht wurde, gelang auch der Durchbruch bei der Einfachheit. Svelte gewann in der Folge stark an Popularität.

Abbildung - Das offizielle Svelte-Logo

Das offizielle Svelte-Logo

Ein Blick unter die Haube

Um zu verstehen, wie es Svelte schafft, klein, schnell und so reduziert in der Syntax zu sein, muss man verstehen, wie Svelte eigentlich funktioniert. Der Hauptteil der Arbeit geschieht zur Compile-Zeit, und nicht zur Laufzeit. React beispielsweise lädt eine Runtime und benötigt darüber hinaus den Virtual DOM, um lauffähig zu sein. Svelte dagegen nimmt den Entwickler-Code und generiert imperativen Laufzeit-Code, der nur noch eine minimale Runtime und ein paar Helfermethoden für weniger Codeduplikation enthält. Der Compiler entfernt darüber hinaus jegliche nicht benötigten Features aus dem Kompilat. So schafft es ein minimales Hello World-Beispiel auf sagenhafte 2,5 Kilobytes – vor Browserkomprimierung.

Die Performance wird durch den Compiler ebenfalls optimiert. Wieder der Vergleich mit React: Facebooks UI-Library führt nach jedem Update einen Diff auf dem gesamten Virtual DOM aus und rendert nur das neu, was sich geändert hat. Svelte hingegen weiß schon vor Ausführung, was sich wann ändern kann. Der Compiler fügt an den entsprechenden Stellen imperative Statements ein, die die Variable der Komponente als dirty markieren. Für den nächsten Browser-Repaint wird ein Rerender eingestellt, welcher zusammen mit den anderen als dirty markierten Komponenten und Variablen abgearbeitet wird. Aus diesem Grund kann sich Svelte auch Performancekrücken wie shouldComponentUpdate sparen, was den Code zugleich einfacher macht.

Überhaupt: Einfachheit wird bei Svelte großgeschrieben. Der gesamte Rewrite für Version 3 zielte genau darauf ab: Mache es dem Entwickler so einfach wie möglich, Code zu schreiben und entferne jegliche unnötige Syntax. Das Ergebnis ist beeindruckend, und gerade zu Anfang ist man immer wieder überrascht, was Svelte alles automagisch herausfindet. Anfangs mag manche Syntax – auch aus diesem Grund – gewöhnungsbedürftig sein, doch geht das Schreiben von Svelte-Komponenten schnell in Fleisch und Blut über.

Wie sieht es nun aus, eine Anwendung in Svelte zu schreiben? Das wollen wir uns im Folgenden anhand einer Bücherliste-App anschauen.

Abbildung - So sieht das Endergebnis aus

So sieht das Endergebnis aus

Codebeispiel Bücherliste-App – erste Schritte

Beginnen wir mit der simpelsten Form der Bücherliste-App und sparen uns zunächst Styling sowie ein (Fake-)Backend.

Als Erstes legen wir eine statische Liste an.

Wie man sieht, kommt das Aussehen einer Svelte-Komponente dem einer HTML-Datei verdächtig nahe. Im script-Tag schreiben wir JavaScript-Code, darunter folgt HTML-Code mit einigen Svelte-Besonderheiten. Wann immer ein Moustache-Tag ({ oder }) erscheint, betreten wir Svelte-Land. Im ersten Fall sehen wir die Verwendung eines Loops. Dieser beginnt mit {#each und schließt mit {/each}. Alles innerhalb des Loops wird wiederholt gerendert. In diesem Fall ist dies ein Listenelement, welches den Wert der Listenelementvariable book als String rendert.

Im nächsten Schritt werden wir das Anlegen von Büchern umsetzen. Dazu fügen wir ein input-Element hinzu, auf dessen Eingaben wir reagieren.

Neu im JavaScript-Code sind die Variable newBook und die Funktion addBook. Mit dem Ausdruck bind:value={newBook} verknüpfen wir die Variable mit dem input-Element. Dies ist ein Two-Way-Binding: Änderungen an der Variablen im Code führen zu einem Neurendern des input-Elements, umgekehrt führen Nutzereingaben zu einem Update des Variablenwerts.

Mit on:<eventname> werden in Svelte Event-Listener an Elemente gebunden. In unserem Beispiel schreiben wir on:keydown={addBook}, womit wir bei jedem keydown-Event die Methode addBook aufrufen. Diese reagiert auf das Drücken der Entertaste, indem es das neue Buch der Liste hinzufügt und danach den input-Text leert. Hierbei sehen wir schön die reduzierte Syntax von Svelte: Es ist kein explizites Update in Form von setState oder ähnlichem nötig, der Compiler erkennt unseren Änderungswunsch und wird Liste und Input neu rendern.

Unterkomponente erstellen und Input-Properties definieren

Mit unserer jetzigen Bücherliste-App können wir Bücher eintragen, aber nicht löschen. Wir müssen also unser Listenelement erweitern. Damit unser Code sauber bleibt – und wir mehr von Sveltes Features zu sehen bekommen – trennen wir dafür das Listenelement in eine eigene Komponente auf.

Die Komponente bietet im ersten Schritt noch keine neue Funktionalität. Wir sehen hier aber, wie wir Inputs (Angular-Sprech) bzw. Props (React-Sprech) auf Komponenten definieren können. Mit export let book geben wir an, dass die Komponente eine Property mit dem Namen book von außen akzeptiert. Die Verwendung in unserer Hauptkomponente sieht dann folgendermaßen aus:

Das Einfügen der Komponente ist denkbar einfach: Wir importieren sie als default import und nutzen den Namen als Tag. Das book-Property geben wir über book={book} hinein. Alternativ können wir in diesem Fall auch die Kurzschreibweise {book} verwenden, da die Variable genauso wie das Input-Property heißt.

Events für Komponenten definieren

Als Nächstes erweitern wir die Book-Komponente, sodass wir Bücher auch wieder löschen können. Dazu definieren wir ein Event-Binding auf der Komponente, das feuert, wenn der Nutzer das Buch löschen will.

Um dies umzusetzen, nutzen wir createEventDispatcher. Den Dispatcher rufen wir als erstes Argument mit einem String auf, der den Eventnamen angibt. Das zweite Argument nimmt eventuelle Eventparameter entgegen, in diesem Fall den Buchnamen. In der Vaterkomponente hören wir auf das Event wie auf andere Events auch mit on:<eventName>, in diesem Fall also on:deleteBook. Der Eventparameter wird in event.detail mitgegeben.

An dieser Stelle sei erwähnt, dass wir alternativ wie in React mit Callback-Props arbeiten, also eine Funktion als Input-Property hineingeben können, die dann aufgerufen wird. Welche Variante genutzt wird, ist letztlich vor allem persönlicher Geschmack.

Abbildung - Blick unter die Haube gefällig? Der Online-Editor auf der offiziellen Svelte-Webseite zeigt Ihnen, wie der generierte Code aussieht

Blick unter die Haube gefällig? Der Online-Editor auf der offiziellen Svelte-Webseite zeigt Ihnen, wie der generierte Code aussieht

Stores für State Management nutzen

Um unsere Daten zu persistieren, nutzen wir der Einfachheit halber den localStorage. Die Zustandsverwaltung und -persistierung soll aber nicht länger Teil der Komponente sein, sondern ausgelagert werden. Hierfür bietet sich das store-Modul von Svelte an, welches im Core bereits enthalten ist.

Teil des store-Moduls ist die Funktion writable, die wir verwenden werden. Ein writable bietet zur Manipulation die Methoden set und update und zum Lesen die Methode subscribe. Mit diesem Grundbaustein können wir uns sehr einfach unseren eigenen globalen Zustandsverwalter bauen:

Wir nutzen Sveltes writable, um einen Store zu erstellen. Öffentlich verfügbar ist aber nur die subscribe-Methode, der Rest wird über fachliche Methoden gehandhabt, die intern den Store aktualisieren.

Das Ganze einzubinden, ist denkbar einfach. Wir importieren den books-Store und delegieren die Bücherlistenverwaltung an ihn.

Besonders elegant gelöst ist das Reagieren auf Updates des books-Stores. Nirgendwo ist ein subscribe-unsubscribe-Pattern zu sehen. Stattdessen schreiben wir einfach $books. Der Compiler erkennt, dass es eine entsprechende Variable mit dem Namen books gibt, welche eine subscribe-Methode besitzt, und kann den Code für uns generieren. Hieran zeigt sich, wie sehr bei der Entwicklung von Svelte auf eine gute Developer-Experience geachtet wurde, und dass ein Compiler Dinge vereinfachen oder erst möglich machen kann, an die man vorher gar nicht denken konnte.

Übrigens: Wem das subscribe-Pattern verdächtig ähnlich zu RxJS-Observables erscheint, der liegt richtig. In der Tat können in Svelte-Komponenten RxJS-Observables genauso mit der $-Syntax genutzt werden, was deren Nutzung sehr einfach macht und in der RxJS-Community große Begeisterung ausgelöst hat. Generell gilt: Alles, was dem subscribe-unsubscribe-Pattern folgt, kann mit der $-Syntax genutzt werden.

Abgeleitete Werte – Anzahl der Bücher anzeigen

Als Nächstes möchten wir unter der Liste die Anzahl der Bücher anzeigen. Da diese Zahl aus der Liste ableitbar ist, soll hierfür kein neuer Zustand eingeführt werden. Hierfür nutzen wir Reactive Declarations.

Reactive Declarations werden durch ein $: zu Beginn der Zeile gekennzeichnet. Der Compiler weiß dadurch, dass er die Variable jedes Mal aktualisieren muss, wenn eine der Variablen sich geändert hat, aus denen sie sich ableitet. In diesem Fall wird also bei jedem Update am books-Store die Variable neu berechnet. Das ist übrigens gültige JavaScript-Syntax – und ein weiterer Beleg dafür, wie wir mit minimalem Boilerplate in Svelte Code schreiben können.

Schöner wohnen – Styles und Transitions

Zu guter Letzt wollen wir unsere Bücher-App optisch verschönern. Zunächst stylen wir dafür die li– und ul-Elemente.

Wie wir sehen, werden die Elemente anhand ihres Tags gestaltet. Über ein Überlappen mit anderen Styles müssen wir uns keine Gedanken machen: Alle Styles gelten nur für die gegebene Komponente. Nur wenn die Selektoren mit :global(…) umschlossen sind, gelten sie über die Komponente hinaus.

Zum Abschluss nutzen wir die transition-Direktive auf dem li-Tag, um ein neues Buch mit einem Fade-in-Effekt erscheinen zu lassen.

Die transition-Direktive ermöglicht es uns, sehr einfach Übergänge zu definieren. Vorgefertigte Übergänge wie fade werden von Svelte bereitgestellt, eigene schreiben ist nicht schwer. Für allgemeinere Fälle gibt es die animation-Direktive, die ebenfalls mit vorgefertigten Animationen wie flip aufwartet. Die Animationen werden, wenn möglich, komplett über CSS gesteuert und nur wenn nicht anders möglich über JavaScript ausgeführt.

Hier zeigt sich schön der Arbeitseinfluss von Richard Harris: Für einen Redakteur, der interaktive Grafiken erstellt, sind Animationen essentiell, weshalb sie auch in Svelte ein Core-Feature sind.

Abbildung - Links: Die Liste vor Styling und Animationen. Rechts: Der Button wurde gestyled, und die Animation sorgt für ein Ausfaden des gelöschten Buchs

Links: Die Liste vor Styling und Animationen. Rechts: Der Button wurde gestyled, und die Animation sorgt für ein Ausfaden des gelöschten Buchs

Ist Svelte „Enterprise-ready“?

Die Bücherlisten-App deckt natürlich nur einen kleinen Teil des Feature-Umfangs von Svelte ab. Lifecycle-Methoden, die Context-API, Server-Side-Rendering out of the box, oder die await-Syntax, die das Rendern von Promises sehr einfach macht, haben wir gar nicht benötigt. Wer sich einen schnellen Überblick verschaffen will, dem sei das Tutorial auf der offiziellen Webseite ans Herz gelegt.

Bleibt die Frage nach der Reife – kann man Svelte guten Gewissens im nächsten Projekt einsetzen?

Ein gewichtiger Punkt für Manager ist die erwartete Lebenszeit des Frameworks und der Support einer großen Firma. Da Svelte Version 3 noch recht neu ist und sich zunehmender Beliebtheit erfreut, dürfte es die nächsten Jahre sicher aktiv weiterentwickelt werden. Eine Firma mit entsprechenden Ressourcen steht allerdings nicht hinter Svelte. Dass das kein Nachteil sein muss, hat aber bereits Vue.js bewiesen.

Für die Entwicklungsgeschwindigkeit sind vor allem Community und Ökosystem relevant. Gibt es umfangreiche Tutorials, wird bei Fragen schnell geholfen, und gibt es für alle gängigen Probleme eine Library? Hier ist Svelte natürlich noch am Anfang und liegt gegenüber Frameworks wie React noch weit zurück. Doch auch hier ist der Trend vielversprechend: Tutorials schießen momentan wie Pilze aus dem Boden, und auch die Libraries werden stetig mehr. Natürlich sind diese noch nicht in einem Reifegrad wie bei vergleichbaren Frameworks. So gibt es noch keinen Platzhirsch bei einer Formular- oder Routing-Library – Dinge, die Svelte nicht im Core mitliefert. Andererseits ist es sehr viel einfacher, pure JavaScript-Libraries in Svelte zu integrieren.

Wie sieht es mit der Nutzung von Sprachen wie TypeScript und Less/SCSS aus? Hier kann Svelte mittlerweile liefern. Es gibt einen offiziellen Präprozessor, der viele gängige Sprachen unterstützt. Editorunterstützung ist ebenfalls vorhanden. Die Community arbeitet aktiv an einem sogenannten Language-Server, welcher in allen IDEs, die das Language Server Protocol unterstützen, genutzt werden kann. Die entsprechenden Extensions stehen unter anderem für VSCode („Svelte for VSCode“) und Vim („coc-svelte“) bereit. Für IntelliJ/WebStorm muss eine separate Lösung implementiert werden, doch auch diese wird aktiv entwickelt und seit neuestem sogar offiziell von Jetbrains unterstützt.

Zusammengefasst sieht man hier das Henne-Ei-Problem, mit dem alle aufstrebenden Frameworks zu kämpfen haben: Viele Entwickler sind aufgrund des Ökosystems noch zögerlich, aber dieses kann sich aus diesem Grund nur schwer vergrößern. Dennoch spricht der Trend klar für Svelte.

Ausprobieren!

Wie wir gesehen haben, ist Svelte nicht ohne Grund der neue Stern am Web-Frontend-Himmel. Es übernimmt bewährte Konzepte aus der React/Vue.js/Angular-Welt und schafft es gleichzeitig, den Boilerplate-Code auf ein Minimum zu reduzieren. Code mit Svelte zu schreiben, ist erfrischend reduziert und simpel, ohne einzuschränken. Dadurch, dass die Hauptarbeit des Frameworks während des Kompilierens geschieht, entstehen performante Anwendungen, die gegenüber anderen Frameworks erstaunlich klein sind – die Beispiel-Bücher-App kommt auf nicht einmal 9 Kilobytes. Außerdem ermöglicht es der Compiler, Syntax-Konstrukte einzuführen, die den Code entschlacken – Entwickler können sich so auf das Wesentliche konzentrieren.

Allerdings steht Svelte, was das Ökosystem angeht, noch recht am Anfang. Dennoch ist ein genauer Blick lohnenswert, auch für das nächste größere Projekt. Denn Svelte bietet alles, um skalierbare Anwendungen zu bauen. Daher: Ausprobieren!

Simon Holthausen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Die von Ihnen hier erhobenen Daten werden von der Host Europe GmbH zur Veröffentlichung Ihres Beitrags in diesem Blog verarbeitet. Weitere Informationen entnehmen Sie bitte folgendem Link: www.hosteurope.de/AGB/Datenschutzerklaerung/