Getting started with Svelte

Svelte or Svelte JS is a frontend framework that can be used in a similar fashion as React and Vue. Svelte does a lot of things differently and prides itself to be fast and simple. In parts that is, because Svelte doesn't use a virtual DOM, like React, and relies a lot on the classic way of building websites and applications with HTML CSS and JS and sprinkling it with some useful additions.

Just like other frameworks, Svelte relies on one or more components, usually stored as *.svelte files and we usually want an entry file called main.js and our initially loaded component, App.svelte. Let's kickstart an example application, by installing Svelte via npx:

npx degit sveltejs/template svelte-app
npm install
npm run dev

This will get us started with the following folder structure, with src being the folder that we'll focus on for now, because holds our entry point and components.

command line
├── ...
├── public
├── scripts
├── src
├── main.js
├── App.svelte
└── ...
├── package.json

The entry file can be very simple when starting a new project. All we do here is declare a target to append our application and define the initial component that holds the rest of our application. We can also pass different props to our app from here.

import App from './App.svelte';

const app = new App({
    target: document.body,
    props: {
        name: 'my first app',
        version: '1.0.0'
    }
});

export default app;

And because we're using App.svelte as our parent component, let's dive in and look at how components in Svelte are generally structured. This is where Svelte really differs from React and Vue and simply lets us write HTML with optional script and style blocks. That means the simplest component can be just HTML, but we're free to use JS and CSS. Every CSS we write inside a component is scoped to that specific component, so styling a <p> tag in one component will not set the styles of every paragraph.

<script>
    // ...
</script>

<main>
    <h1>Hello World!</h1>
</main>

<style>
    /* ... */
</style>

A simple Svelte component example

Now to start structuring our application and getting our hands dirty a little more, let's look at importing another component and actually adding some functionality, pulling data from an external API. For this example, we'll fetch a random dad joke and display it on our page. When we press a button, the fetch function will be called again and another dad joke is displayed.

<script>
    async function fetchData() {
        const res = await fetch("https://icanhazdadjoke.com", {
            headers: {
                Accept: "application/json",
            },
        });
        const data = await res.json();
        return data.joke;
    }

    let joke = fetchData();

    function handleClick() {
        joke = fetchData();
    }
</script>

<button on:click={handleClick}>Get a random dad joke </button>

<h2>Here's a random dad joke:</h2>

{#await joke}
    <p>...waiting</p>
{:then joke}
    <p>{joke}</p>
{:catch error}
    <p style="color: red">Couldn't fetch a joke...</p>
{/await}


In the example above we can see that our JavaScript is not any different than it would be without a framework. In the HTML section, however, we see the first Svelte blocks, one handler, used to reload a joke and a special logic block, used to await a response from our async function fetchData(). Handlers in Svelte look a lot like they do in Vue.js and the different logic blocks are fairly easy to remember. Here's a quick look at two common blocks: a simple if condition and each loop.

<!-- If condition --->
{#if user.loggedIn}
    <button on:click={toggle}>
        Log out
    </button>
{/if}

<!-- Each block-->
{#each things as thing}
    <Thing name={thing.name}/>
{/each}

Data binding

Just like we can pass data from parent to child components in Svelte, we can also rely on reactive variables/data binding. The bind: directive allows us to automatically set name to the input field's current value. In the same manner, we can make other form elements reactive, such as the select element below.

<script>
    let name = 'world';
    let selected;
</script>

<input bind:value={name}>
<h1>Hello {name}!</h1>

<select bind:value={selected} on:change="{() => answer = ''}">
    <!-- ... -->
</select>


Lifecycle hooks and stores

Like other frameworks, Svelte gives us a few useful lifecycle hooks that allow us to run code at certain stages of a component's lifecycle. We can make use of the methods onMount, onDestroy, beforeUpdate and afterUpdate after we imported them in our component:

import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte'

A common use case for the onMount function is fetching data from external endpoints. Doing that, we can rewrite the example above to fetch a dad joke without using an await block in our HTML. Instead, we start fetching the data right after the component is mounted and only return the final joke.

<script>
    import { onMount } from 'svelte'

    let joke = "loading joke..."
    onMount(async () => {
        const res = await fetch("https://icanhazdadjoke.com", {
            headers: {
                Accept: "application/json",
            },
        });
        let json = await res.json();
        joke = json.joke
    })
</script>
<h2>Here's a random dad joke:</h2>
<p>{joke}</p>

Svelte also brings its own storing mechanism, which helps a lot with keeping state in sync across components. Under the hood, a store is a simple object that we can subscribe to, to be notified of any changes. In order to store one of the jokes from the example above, we need a writable store. Writable stores generally have two more functions, update and set that let us manipulate the stored values. In our application, we can achieve this by creating a new file, called stores.js

<script>
    // stores.js
    import { writable } from 'svelte/store';
    export const globalJoke = writable("no joke stored yet...");
</script>

We can then import our store or specific values inside it in any other component and we're able to read and mutate the stored values as needed:

<script>
    // any other component
    import { globalJoke } from './stores.js';
    globalJoke.update("Did you hear about the bread factory burning down? They say the business is toast.")
</script>

Further reading

That's only the basics that should help you get started with Svelte. If you want to dig deeper from here, the official tutorial is a great place to start, as well as the documentation. The Svelte site also offers an interactive playground that you can use to start getting a feel for the library.

JavaScript
frameworks