image: svelte5.webp:0:80

Frontend-Ent­wick­lung mit Svelte

Rich Harris

In diesem Tutorial werden wir die Grundlagen von Svelte ken­nen­ler­nen und eine einfache Anwendung erstellen. Svelte ist ein modernes Frontend-Frame­work, das es dir er­mög­licht, inter­ak­ti­ve Web­sei­ten zu erstellen. Du kannst damit z. B. kleine Spiele oder Web­an­wen­dun­gen entwickeln. In diesem Tutorial werden wir einen »Rubik's Cube Timer« programmieren – also eine Stoppuhr, die die Zeit misst, die du für das Lösen eines Rubik's Cube benötigst.

Bevor du dieses Tutorial beginnst, solltest du dich ein wenig mit HTML und CSS auskennen. Wenn du noch nie mit diesen Technologien gear­bei­tet hast, empfehlen wir dir, zuerst das Tutorial zu Statischen Web­sei­ten durchzuarbeiten.

Was ist Svelte?

Svelte ist ein modernes Frontend-Frame­work. Es gab vorher schon viele andere Frontend-Frame­works, wie z. B. React (2013), Vue (2014) und Angular (2016). Diese Frame­works haben alle ihre Vor- und Nachteile. Svelte ist ein relativ neues Frame­work, das 2016 von Rich Harris – einem Journalisten und Softwareentwickler – ent­wick­elt wur­de.

1. Vorbereitung

Stelle zuerst sicher, dass du keinen Ordner geöffnet hast. Um sicherzugehen, drücke einfach den Shortcut für »Ordner schließen«: StrgK und dann F. Dein Work­space sollte jetzt ungefähr so aussehen:

Svelte-Er­wei­te­rung installieren

Klicke dazu auf das Er­wei­te­rungs-Symbol in der Seitenleiste oder drücke StrgShiftX. Suche nach der Er­wei­te­rung »Svelte for VS Code« und installiere sie.

Svelte-Projekt erstellen

Um ein neues Svelte-Projekt zu erstellen, öffne ein Ter­mi­nal und gib folgenden Befehl ein:

npx sv create rubik-timer

Du wirst vermutlich gefragt, ob das sv-Paket installiert werden soll:

Bestätige mit Enter. Du wirst nun gefragt, welches Template du verwenden möchtest. Wähle das Standard-Template »SvelteKit minimal« aus, indem du Enter drückst:

Bei der nächsten Frage wäre die richtige Antwort »TypeScript«, aber da wir in diesem Tutorial kein TypeScript verwenden, sondern normales JavaScript, wähle hier bitte »No« aus:

Du wirst als nächstes gefragt, ob du schon ein paar Plugins installieren möchtest. Da wir keine Plugins benötigen, kannst du einfach Enter drücken:

Als letztes wirst du gefragt, welchen Paketmanager du verwenden möchtest. Wähle hier »npm« aus, indem du Enter drückst:

Daraufhin musst du noch ein paar Sekunden warten, bis alle Abhängigkeiten installiert sind und das Projekt erstellt wur­de. Wenn du die Meldung »Project created« siehst, hat alles geklappt:

Falls du von vorne beginnen möchtest, kannst du einfach das Verzeichnis /workspace/rubik-timer löschen und von vorn beginnen.

Öffne nun das Verzeichnis, indem du entweder im Menü »File« / »Open Folder…« auswählst oder einfach StrgK und dann StrgO drückst. Wähle den Ordner rubik-timer aus:

2. Development-Server starten

Bevor wir den Ent­wick­lungs-Server im Work­space starten können, müssen wir noch eine Kleinigkeit anpassen. Öffne die Datei package.json und ändere den Eintrag für "dev" von "vite dev" in "vite dev --host --open".

Öffne nun die Datei vite.config.js und füge einen Eintrag server hinzu, um den Server für Anfragen aus deinem Work­space zu öffnen:

Du musst also den folgenden Eintrag hinzufügen:

server: {
    allowedHosts: ['workspace.hackschule.de']
}
Achte auf das Komma am Ende der Zeile darüber! Wenn du das Komma vergisst, wird die Datei nicht richtig interpretiert und du be­kommst eine Fehlermeldung.

Anschließend kannst du den Ent­wick­lungs-Server starten, indem du im Ter­mi­nal folgenden Befehl eingibst:

npm run dev

Wenn alles geklappt hat, sollte sich deine Webseite automatisch in einem neuen Tab öffnen:

Tipp: Ziehe deinen Work­space und die Vorschau nebeneinander, damit du beide Fenster gleichzeitig sehen kannst.
Wenn etwas nicht funktioniert, kannst du den Server jederzeit beenden, indem du im Ter­mi­nal StrgC drückst. Du kannst den Server dann wieder neu starten, indem du npm run dev eingibst.

3. Webseite implementieren

Jetzt, wo wir alles eingerichtet haben, können wir mit dem Pro­gram­mier­en beginnen. Wir werden eine einfache Stoppuhr erstellen, die die Zeit misst, die du für das Lösen eines Rubikwürfels benötigst.

Du kennst dich bereits mit HTML und CSS aus, und jetzt werden wir auch ein wenig JavaScript verwenden, um die Webseite interaktiv zu machen. Bei Svelte werden alle drei Technologien in einer Datei kombiniert, die eine Komponente darstellt. Eine Komponente ist ein wiederverwendbarer Baustein, der eine bestimmte Funktionalität bereitstellt. In unserem Fall wird die Komponente die Stoppuhr darstellen.

Öffne die Datei src/routes/+page.svelte. Diese Datei enthält den Quelltext für unsere Webseite. Du solltest etwas Code sehen, der ungefähr so aussieht:

<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
Das Öffnen von Da­tei­en geht besonders schnell, wenn du StrgP drückst und dann den Da­tei­na­men eingibst. Probier es einmal aus, indem du die Tastenkombination drückst und dann »page« eingibst! So kannst du die Datei schnell finden, ohne durch alle Ordner navigieren zu müssen.

Du kannst den Code jetzt einfach löschen und durch den folgenden ersetzen:

<script>
</script>

<div class="main">
    <h1>Rubik's Cube Timer</h1>
</div>

<style>
</style>

Du siehst drei Abschnitte:

  • <script>: Hier kommt der JavaScript-Code hin, der die Logik der Webseite enthält.
  • <div class="main">: Hier kommt der HTML-Code hin, der die Struktur der Webseite definiert. Wir haben ein <div>-Element mit der Klasse main erstellt, das den Titel der Webseite enthält.
  • <style>: Hier kommt der CSS-Code hin, der das Aussehen der Seite bestimmt.

Wir beginnen mit dem CSS-Code für die Webseite. Füge den folgenden Code in den <style>-Tag ein, um den Inhalt des .main-Elements zu zentrieren:

.main {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    margin: 0 1em;
    user-select: none;
}

Wenn du jetzt die Seite aktualisierst, solltest du den Titel »Rubik's Cube Timer« in der Mitte der Seite sehen. Allerdings stört am rechten Rand noch ein Scrollbalken, den wir mit folgendem CSS-Code in der Datei src/app.html entfernen können:

html,
body {
    margin: 0;
}

Füge den Code in einen <style>-Tag in der Datei src/app.html ein (am besten nach dem </body>). Wenn du die Seite jetzt aktualisierst, sollte der Scrollbalken verschwunden sein.

Modellierung

Um die Stoppuhr zu programmieren, brauchen wir eine Idee, wie sie benutzt werden soll – kümmern wir uns um die »Busi­ness-Logik«! Die Stoppuhr kann in verschiedenen Zuständen sein:

  • Zustand 0: Zu Beginn ist die Stoppuhr gestoppt. Wenn man die Leertaste drückt, kommt man in Zustand 1.
  • Zustand 1: Um Fehlstarts zu vermeiden, wird überprüft, ob die Leertaste mindestens 500 ms lang gedrückt wird. Falls nicht, geht es zurück zu Zustand 0, anderenfalls zu Zustand 2.
  • Zustand 2: Die Stoppuhr färbt sich grün und ist bereit. Wenn die Leertaste jetzt losgelassen wird, kommt man in Zustand 3.
  • Zustand 3: Die Stoppuhr läuft. Wenn die Leertaste erneut gedrückt wird, kommt man in Zustand 4.
  • Zustand 4: Die Stoppuhr wird gestoppt.

Daraus ergibt sich folgender Ablauf:

Um den Zustand auf der Webseite zu speichern, deklarieren wir eine Variable state im <script>-Tag:

let state = $state(0);
// 0 : idle
// 1 : space pressed
// 2 : space pressed for 500 ms
// 3 : timer running
// 4 : timer stopped

Die Variable ist keine normale JavaScript-Variable, sondern eine Svelte-Variable – man er­kennt es daran, dass sie in $state( ... ) steht. Das bedeutet, dass wir sie in unseren HTML-Code einbauen können und die Seite automatisch aktualisiert wird, wenn sich der Wert der Variable ändert. Das ist eine der Stärken von Svelte: Es macht es einfach, inter­ak­ti­ve Web­sei­ten zu erstellen!

Wir können die Variable state jetzt in unserem HTML-Code verwenden, um den aktuellen Zustand der Stoppuhr anzuzeigen. Füge den folgenden Code in den <div class="main">-Tag unterhalb der Überschrift ein:

<p>State = {state}</p>

In deiner Vorschau sollte jetzt der Text »State = 0« erscheinen:

Tastendruck erkennen

Um zu erkennen, wann die Leertaste gedrückt wird, müssen wir einen Event-Listener hinzufügen. Das sollten wir tun, nachdem die Seite vollständig geladen ist. Dafür brauchen wir den onMount-Lifecycle-Hook von Svelte. Dieser Hook wird aufgerufen, wenn die Komponente in den DOM eingefügt wird. Füge den folgenden Code ganz oben in den <script>-Tag ein:

import { onMount } from 'svelte';

Wir können nun den onMount-Hook verwenden, um den Event-Listener hinzuzufügen. Füge den folgenden Code in das <script>-Tag ein:

function handleKeyDown() {
    state = 1;
}

onMount(() => {
    document.addEventListener("keydown", (e) => {
        if (e.code === "Space") {
            handleKeyDown();
        }
    });
});

Wir definieren eine Funktion handleKeyDown, die den Zustand auf 1 setzt (wir werden die Logik später noch erweitern). Dann fügen wir im onMount-Hook einen Event-Listener hinzu, der die Funktion handleKeyDown aufruft, wenn die Leertaste gedrückt wird.

Achte beim Einfügen von Code darauf, dass du eine einheitliche Einrückung verwendest. Mach dich mit den Möglichkeiten in VS Code vertraut, um den Code einzurücken. Du kannst z. B. den gesamten Code markieren und dann Tab drücken, um ihn einzurücken, oder ShiftTab, um ihn wieder auszurücken. VS Code kann Code auch automatisch einrücken – drücke dazu StrgShiftP und gib »Reindent Lines« ein.

Wenn du die Seite jetzt aktualisierst und die Leertaste drückst, sollte sich der Zustand auf 1 ändern. Wenn du die Leertaste loslässt, bleibt der Zustand auf 1 stehen. Das liegt daran, dass wir noch keine Logik implementiert haben, um den Zustand zurückzusetzen. Du kannst die Seite aber neu laden, um den Zustand zurückzusetzen.

Wir fügen eine Funktion handleKeyUp hinzu, die den Zustand zurücksetzt, wenn die Leertaste losgelassen wird. Füge den folgenden Code in das <script>-Tag ein:

function handleKeyUp() {
    state = 0;
}

Füge außerdem einen weiteren Event-Listener in onMount hinzu, der die Funktion handleKeyUp aufruft, wenn die Leertaste losgelassen wird:

document.addEventListener("keyup", (e) => {
    if (e.code === "Space") {
        handleKeyUp();
    }
});

Du solltest jetzt sehen, wie der Zustand auf 0 zurückgesetzt wird, wenn du die Leertaste loslässt.

Damit der Timer auch auf dem Handy funktioniert, wo es keine Leertaste gibt, fügen wir noch einen weiteren Event-Listener im onMount-Hook hinzu, der auf das Antippen des Bildschirms reagiert:

document.addEventListener("touchstart", () => handleKeyDown());
document.addEventListener("touchend", () => handleKeyUp());

Wir fügen noch noch ein paar Variablen oben im <script>-Tag hinzu:

let t0 = 0;
let timerString = $state("00:00<span class='small'>.00</span>");
let timeoutId = null;
  • t0 ist die Startzeit des Timers – hiermit berechnen wir später die Zeit, die seit dem Start vergangen ist.
  • timerString ist der Text, der auf der Webseite angezeigt wird. Wir verwenden hier HTML, um die Zeit mit hunderstel Sekunden anzuzeigen. Die CSS-Klasse small soll dafür sorgen, dass die hunderstel Sekunden kleiner dargestellt werden – wir definieren sie später. Dieser Variable ver­wen­det auch wieder $state von Svelte, damit sie im HTML automatisch aktualisiert wird, wenn sich der Wert ändert.
  • timeoutId ist eine ID, die wir später verwenden werden, um den 500 ms-Timeout abzubrechen, falls die Leertaste vorher losgelassen wird.

Im .main-Element fügen wir jetzt noch eine Anleitung und den eigentlichen Timer hinzu:

<p>
    Halte die Leertaste gedrückt, bis der Timer grün wird. Wenn du dann los lässt, beginnt die Zeit zu laufen.
</p>

<p class="timer">{@html timerString}</p>

Im CSS-Abschnitt fügen wir noch ein paar Zeilen hinzu, um den Timer zu formatieren:

.timer {
    font-size: 300%;
    font-weight: bold;
    padding: 0.25em 0.5em;
    border-radius: 0.2em;
    background-color: #eeeeec;

    :global(.small) {
        font-size: 75%;
    }

    :global(&.ready) {
        transition: background-color 0.3s ease-in;
        background-color: #73a946;
    }
}

Da Svelte nor­ma­ler­wei­se allen Code, der nicht ver­wen­det wird, aus Ef­fi­zienzgründen entfernt, müssen wir CSS-Klassen, die nicht von Anfang an schon im HTML-Code vorhanden sind, mit :global(...) kennzeichnen. Das ist hier der Fall, weil die CSS-Klassen ready und small erst später durch JavaScript-Funk­tio­nen hinzugefügt werden.

Wir brauchen eine Funktion, die die Timeranzeige, also die Variable timerString, aktualisiert. Füge den folgenden Code in das <script>-Tag ein:

function updateTimer() {
    if (state != 3) return;

    let t1 = Date.now();
    let duration = (t1 - t0) / 1000.0;

    let minutes = `${Math.floor(duration / 60.0)}`;
    if (minutes.length < 2) minutes = "0" + minutes;

    let seconds = `${Math.floor(duration % 60)}`;
    if (seconds.length < 2) seconds = "0" + seconds;

    let centiseconds = `${Math.floor(duration * 100.0) % 100}`;
    if (centiseconds.length < 2) centiseconds = "0" + centiseconds;

    timerString = `${minutes}:${seconds}<span class='small'>.${centiseconds}</span>`;

    requestAnimationFrame(updateTimer);
}
Die Funktion bricht sofort ab, wenn der Zustand nicht 3 ist. Anderenfalls wird die vergangene Zeit berechnet und in der Variable `timerString` gespeichert. Diese wird dann automatisch aktualisiert, weil wir sie mit `$state` deklariert haben. Anschließend wird mit Hilfe von `requestAnimationFrame` die Funktion `updateTimer` erneut aufgerufen. Das sorgt dafür, dass die Funktion so oft wie möglich aufgerufen wird, ohne den Browser zu überlasten.

Die Funktion handleKeyDown muss jetzt noch angepasst werden, damit sie korrekt zwischen den einzelnen Zuständen wechselt:

function handleKeyDown() {
    if (state === 0) {
        state = 1;
        timeoutId = setTimeout(() => {
            if (state === 1) {
                state = 2;
                document.querySelector(".timer")?.classList.add("ready");
            }
        }, 500);
    } else if (state === 3) {
        state = 4;
    }
}

Wenn der Zustand 0 ist, wird er auf 1 gesetzt und ein Timeout von 500 ms gestartet. Am Ende dieses Timeouts wird geschaut, ob der Zustand immer noch 1 ist. Wenn ja, wird er auf 2 gesetzt und die Klasse ready zur Timeranzeige hinzugefügt. Diese Klasse sorgt dafür, dass die Stoppuhr grün wird.

Ist der Zustand jedoch 3, wird er auf 4 gesetzt (die Stoppuhr wird gestoppt).

Die Funktion handleKeyUp muss ebenfalls angepasst werden:

function handleKeyUp() {
    if (state === 1) {
        state = 0;
        clearTimeout(timeoutId);
    } else if (state === 2) {
        state = 3;
        t0 = Date.now();
        requestAnimationFrame(updateTimer);
    }
}

Wenn die Taste losgelassen wird, während wir noch im Zustand 1 sind, wird der Zustand auf 0 zurückgesetzt und der 500 ms-Timeout abgebrochen. Wenn der Zustand 2 ist, wird er auf 3 gesetzt und die aktuelle Zeit in der Variable t0 gespeichert. Außerdem wird mit dem Befehl requestAnimationFrame(updateTimer) die Funktion updateTimer einmalig aufgerufen, die die Timeranzeige aktualisiert und dann dafür sorgt, dass sie immer wieder aufgerufen wird.

Der ganzen Code für die Datei src/routes/+page.svelte sieht jetzt so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<script>
    import { onMount } from "svelte";

    let state = $state(0);
    // 0 : idle
    // 1 : space pressed
    // 2 : space pressed for 500 ms
    // 3 : timer running
    // 4 : timer stopped
    let t0 = 0;
    let timerString = $state("00:00<span class='small'>.00</span>");
    let timeoutId = null;

    function updateTimer() {
        if (state != 3) return;

        let t1 = Date.now();
        let duration = (t1 - t0) / 1000.0;

        let minutes = `${Math.floor(duration / 60.0)}`;
        if (minutes.length < 2) minutes = "0" + minutes;

        let seconds = `${Math.floor(duration % 60)}`;
        if (seconds.length < 2) seconds = "0" + seconds;

        let centiseconds = `${Math.floor(duration * 100.0) % 100}`;
        if (centiseconds.length < 2) centiseconds = "0" + centiseconds;

        timerString = `${minutes}:${seconds}<span class='small'>.${centiseconds}</span>`;

        requestAnimationFrame(updateTimer);
    }

    function handleKeyDown() {
        if (state === 0) {
            state = 1;
            timeoutId = setTimeout(() => {
                if (state === 1) {
                    state = 2;
                    document.querySelector(".timer")?.classList.add("ready");
                }
            }, 500);
        } else if (state === 3) {
            state = 4;
        }
    }

    function handleKeyUp() {
        if (state === 1) {
            state = 0;
            clearTimeout(timeoutId);
        } else if (state === 2) {
            state = 3;
            t0 = Date.now();
            requestAnimationFrame(updateTimer);
        }
    }

    onMount(() => {
        document.addEventListener("keydown", (e) => {
            if (e.code === "Space") {
                handleKeyDown();
            }
        });
        document.addEventListener("keyup", (e) => {
            if (e.code === "Space") {
                handleKeyUp();
            }
        });
        document.addEventListener("touchstart", () => handleKeyDown());
        document.addEventListener("touchend", () => handleKeyUp());
    });
</script>

<div class="main">
    <h1>Rubik's Cube Timer</h1>

    <p>State = {state}</p>

    <p>
        Halte die Leertaste gedrückt, bis der Timer grün wird. Wenn du dann los
        lässt, beginnt die Zeit zu laufen.
    </p>

    <p class="timer">{@html timerString}</p>
</div>

<style>
    .main {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        min-height: 100vh;
        margin: 0 1em;
        user-select: none;
    }
    .timer {
        font-size: 300%;
        font-weight: bold;
        padding: 0.25em 0.5em;
        border-radius: 0.2em;
        background-color: #eeeeec;

        :global(.small) {
            font-size: 75%;
        }

        :global(&.ready) {
            transition: background-color 0.3s ease-in;
            background-color: #73a946;
        }
    }
</style>

Deine Seite sollte jetzt so aussehen:

4. Webseite erweitern

Jetzt, wo die Stoppuhr funktioniert, können wir uns um das Styling kümmern. Wir haben bereits ein paar CSS-Regeln hinzugefügt, aber es gibt noch ein paar Dinge, die wir verbessern können.

Bessere Schriftarten

Wir können die Schriftart der Webseite ändern, um sie ansprechender zu gestalten. Dazu verwenden wir Google Fonts. Füge den folgenden Code in den <head>-Tag der Datei src/app.html ein:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,700;1,400;1,700&family=Quicksand:wght@300..700&display=swap" rel="stylesheet">

Ändere außerdem den CSS-Code in der Datei src/routes/+page.svelte, so dass die Schriftarten ver­wen­det werden:

.main {
    font-family: Quicksand;
}
.timer {
    font-family: "IBM Plex Mono";
}

Du solltest jetzt sehen, dass die Schriftart der Webseite geändert wur­de. Wenn du die Seite aktualisierst, sollte sie jetzt so aussehen:

Bootstrap einbinden und Reset-Button hinzufügen

Bootstrap ist ein beliebtes CSS-Frame­work, das dir hilft, deine Webseite schnell und einfach zu gestalten. Du kannst es einbinden, indem du den folgenden Code in den <head>-Tag der Datei src/app.html einfügst:

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">

Jetzt kannst du Bootstrap-Klassen verwenden, um deine Webseite zu gestalten. Unter anderem stellt Bootstrap Klassen zum Styling von Buttons zur Verfügung, die wir für unseren Reset-Button verwenden können. Füge den folgenden Code in den <div class="main">-Tag ein, um einen Reset-Button hinzuzufügen:

<button
    id="bu_reset"
    class="btn btn-lg {state < 3 ? 'btn-outline-secondary' : 'btn-warning'}"
    disabled={state < 3 ? "disabled" : ""}
    on:click={resetTimer}>
    Reset
</button>

Wir definieren hier einen Button mit der ID bu_reset, der die Klasse btn von Bootstrap hat. Außerdem verwenden wir die Klasse btn-outline-secondary (graue Umrandung), wenn state kleiner als 3 ist, und ansonsten die Klasse btn-warning (gelbe Farbe). Außerdem wird der Button deaktiviert, wenn state kleiner als 3 ist. Wenn der Button geklickt wird, wird die Funktion resetTimer aufgerufen.

Wir müssen jetzt noch eine Funktion resetTimer hinzufügen, die den Timer zurücksetzt. Füge den folgenden Code in das <script>-Tag ein (z. B. hinter der Funktion handleKeyUp):

function resetTimer() {
    if (state > 2) {
        state = 0;
        t0 = 0;
        timerString = "00:00<span class='small'>.00</span>";
        document.querySelector(".timer")?.classList.remove("ready");
    }
}

Icons einbinden

Auf dem Reset-Button fehlt noch ein Icon. Wir verwenden dafür Iconify, eine Sammlung von Icons, die du ganz einfach in deine Webseite einfügen kannst. Um die Icons zu verwenden, müssen wir das Iconify-Paket installieren. Das geht ganz einfach mit dem folgenden Befehl:

npm install @iconify/svelte

Wenn du das Paket installiert hast, kannst du die Icons ganz einfach in deine Webseite einfügen. Füge den folgenden Code in den <script>-Tag ein:

import Icon from '@iconify/svelte';

Füge dann den folgenden Code in den <button>-Tag ein (genau vor dem Label »Reset«), um das Icon anzuzeigen:

<Icon icon="material-symbols:device-reset-rounded" class="icon" />
Denke daran, dass du den Ent­wick­lungs-Server neu starten musst, damit du die Seite aufrufen kannst.

Das Icon wird jetzt in dem Button angezeigt. Du kannst die Größe des Icons ändern, indem du die CSS-Klasse icon anpasst. Füge den folgenden Code in den <style>-Tag ein:

:global(.btn .icon) {
    margin-right: 0.25em;
    padding-bottom: 0.1em;
    transform: scale(1.3);
}

Wenn du die Seite jetzt aktualisierst, solltest du den Reset-Button mit dem Icon sehen:

Du kannst dir hier auch andere Icons aussuchen: https://icon-sets.iconify.design/. Du kannst die Icons ganz einfach in deine Webseite einfügen, indem du den Namen des Icons in den <Icon>-Tag einfügst. Zum Beispiel:

<Icon icon="mdi:home" class="icon" />
Es kann sein, dass deine Icons etwas verzögert angezeigt werden. Das ist aber nur in der Vorschau so. Wenn du die Seite als statische Webseite exportierst, werden die Icons sofort angezeigt.

5. Statische Webseite exportieren

Um deine Webseite online zu stellen, bietet es sich an, sie als statische Webseite zu exportieren. Das bedeutet, dass die Webseite in eine HTML-Datei umgewandelt wird, die du dann auf einem Webserver hosten kannst. Gegenüber dynamischen Web­sei­ten, die bei jedem Aufruf neu generiert werden, sind statische Web­sei­ten schneller und benötigen weniger Ressourcen. Außerdem verzichtest du so auf eine relativ große Angriffsfläche, die ein Backend mit sich bringen kann.

Um deine Webseite als statische Webseite zu exportieren, müssen wir erst einen statischen Adapter für Svelte installieren. Das geht ganz einfach mit dem folgenden Befehl:

npm install -D @sveltejs/adapter-static

Anschließend musst du den Adapter in der Datei svelte.config.js aktivieren. Öffne die Datei und ändere adapter-auto in adapter-static:

Wir müssen Svelte jetzt noch mitteilen, dass wir die Webseite als statische Webseite exportieren möchten. Erstelle dazu eine neue Datei src/routes/+layout.js und füge den folgenden Code ein:

export const prerender = true;

Anschließend kannst du den statischen Build erstellen, indem du im Ter­mi­nal folgenden Befehl eingibst:

npm run build

Wenn alles geklappt hat, solltest du ein neues Verzeichnis build in deinem Verzeichnis sehen, das alle Da­tei­en enthält, die du für deine Webseite benötigst.

Du kannst die Seite testen, indem du das build-Verzeichnis öffnest und den Live-Server startest. Sie sollte genauso aussehen und funktionieren wie die Seite, die du mit dem Ent­wick­lungs-Server siehst.

Deine Seite veröffentlichen

Du kannst deine Webseite ganz einfach veröffentlichen, indem du sie auf einen Webserver hochlädst. Es gibt viele kostenlose Hosting-Anbieter, die dir helfen können, deine Webseite online zu stellen. Du kannst deine Seite aber auch gern kostenlos unter einer Subdomain von hackschule.de veröffentlichen (also z. B. meineseite.hackschule.de). Wenn du das möchtest, schreib einfach eine E-Mail an specht@gymnasiumsteglitz.de. Eine Anleitung, wie du auf deinen Webspace zugreifen kannst, findest du hier.