DEV Community

loading...
Cover image for Svelte Web Interfaces with Svelte

Svelte Web Interfaces with Svelte

Jacob Herrington (he/him)
generally mediocre
Updated on ・5 min read

Did anyone else just find out that svelte is a real word? It's pretty much a synonym for lithe or slender.

If you're watching the front-end JavaScript framework ecosystem closely these days, you've probably noticed that JavaScript has started to stabilize. We no longer see a dozen frameworks competing for market share in the JavaScript space. Now, we've got a handful of front-running frameworks and a few niche ones.

Why would someone introduce a new component framework for building user interfaces with JavaScript?

Good question, I'm glad you asked.

Traditional JavaScript frameworks (React is like six years old, we can call that traditional, right?) put a heavy load on the browser even though they take advantage of a virtual DOM. A virtual DOM helps frameworks like React re-render your web interface upon state change performantly. It's an excellent idea.

But it might not be necessary.

So what is wrong with the virtual DOM?

There is nothing wrong with the VDOM, usually. Relying on a virtual DOM is totally fine for most use cases; however, it is still overhead.

There is a top-notch article by Rich Harris that covers how the Svelte project feels about the virtual DOM. To boil it down, a virtual DOM is fine in practice for many applications, but it is not faster than the DOM itself.

An analogous example described in the above article is the C compiler. You could write faster code lower in the stack, but why would you when C is friendly (and therefore productive) and fast enough?

But what if you didn't have to pick between productivity and speed?

With Svelte, you can have the same powerful model you see in React and Vue, without the overhead of the virtual DOM.

What makes Svelte special?

It removes overhead.

The hypothesis behind Svelte is straightforward: Browser-based UI frameworks result in a lot of overhead; it is possible to remove this overhead by handling the framework in a build step outside of the browser. Svelte doesn't have a virtual DOM.

It's a compiler, not a dependency.

Frameworks like Vue and React are dependencies; they interact with your code while it executes. Svelte is a compiler; it interacts with your code before you ever put that code in production — Svelte outputs vanilla JavaScript.

How does it work?

There is some really awesome documentation on svelte.dev, and I plan to write a series of tutorials on Svelte shortly. There is a wonderful REPL available on the Svelte site too.

But, I'll share some code in this article to give you a taste of working in Svelte. You should use the REPL to follow along. 😉

<!-- App.svelte -->

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

<style>
  h1 {
    font-family: Helvetica;
    color: #333;
  }
</style>

<h1>Hello {name}!</h1>
Enter fullscreen mode Exit fullscreen mode

That's weird. It looks like a generic HTML file with one exception:

<h1>Hello {name}!</h1>
Enter fullscreen mode Exit fullscreen mode

What's up with the curly brackets? Svelte makes it easy to drop JavaScript into your markup, just like JSX. For example, we could just as easily do this:

<h1>Hello {name || 'world'}!</h1>
Enter fullscreen mode Exit fullscreen mode

And just like that, we are handling falsey values for the name variable.

If you're following along, you might be confused because I called this a component framework (I'll probably use the words framework and compiler interchangeably, sorry). You'd be forgiven for asking where the component is, but you're looking at the component:

<!-- App.svelte -->

<script>
  let name = 'Jacob';
</script>

<style>
  h1 {
    font-family: Helvetica;
    color: #333;
  }
</style>

<h1>Hello {name || 'world'}!</h1>
Enter fullscreen mode Exit fullscreen mode

What if we want to add another component, we can just make a new file:

<!-- Image.svelte -->

<script>
  export let src;
  export let alt;
</script>

<style>
  h1 {
    font-family: "Comic Sans MS";
    color: #ff0;
  }
</style>

<h1>Check this out!</h1>
<img {src} {alt}>
Enter fullscreen mode Exit fullscreen mode

Now let's import our new component and render it in App.svelte.

<!-- App.svelte -->

<script>
  import Image from './Image.svelte';

  let name = 'Jacob';
</script>

<style>
  h1 {
    font-family: Helvetica;
    color: #333;
  }
</style>

<h1>Hello {name || 'world'}!</h1>
<Image 
    src="https://ksassets.timeincuk.net/wp/uploads/sites/55/2016/04/2014RickAstley_Getty109255193201014-1.jpg"
    alt="The world's most talented musician"
/>
Enter fullscreen mode Exit fullscreen mode

You might notice something really cool about the <h1> tags. The styles from App.svelte don't override the styles from Image.svelte and vice-versa. Styles are scoped to components 🤯.

That's cool and all, but keep in mind that this is a compiler. The code that I'm writing is code for humans (and Svelte allows for some human-friendly code), but we've got to run it through the compiler to get code for the browser.

This is what the browser sees:

CSS:

h1.svelte-iq7gzg{font-family:Helvetica;color:#333}
Enter fullscreen mode Exit fullscreen mode

and javascript:

/* App.svelte generated by Svelte v3.9.2 */
import {
    SvelteComponent,
    append,
    attr,
    destroy_component,
    detach,
    element,
    init,
    insert,
    mount_component,
    noop,
    safe_not_equal,
    space,
    text,
    transition_in,
    transition_out
} from "svelte/internal";
import Image from "./Image.svelte";

function create_fragment(ctx) {
    var h1, t0, t1_value = name || 'world' + "", t1, t2, t3, current;

    var image = new Image({
        props: {
        src: "https://ksassets.timeincuk.net/wp/uploads/sites/55/2016/04/2014RickAstley_Getty109255193201014-1.jpg",
        alt: "The world's most talented musician"
    }
    });

    return {
        c() {
            h1 = element("h1");
            t0 = text("Hello ");
            t1 = text(t1_value);
            t2 = text("!");
            t3 = space();
            image.$$.fragment.c();
            attr(h1, "class", "svelte-iq7gzg");
        },

        m(target, anchor) {
            insert(target, h1, anchor);
            append(h1, t0);
            append(h1, t1);
            append(h1, t2);
            insert(target, t3, anchor);
            mount_component(image, target, anchor);
            current = true;
        },

        p: noop,

        i(local) {
            if (current) return;
            transition_in(image.$$.fragment, local);

            current = true;
        },

        o(local) {
            transition_out(image.$$.fragment, local);
            current = false;
        },

        d(detaching) {
            if (detaching) {
                detach(h1);
                detach(t3);
            }

            destroy_component(image, detaching);
        }
    };
}

let name = 'Jacob';

class App extends SvelteComponent {
    constructor(options) {
        super();
        init(this, options, null, create_fragment, safe_not_equal, []);
    }
}

export default App;
Enter fullscreen mode Exit fullscreen mode

👆This is not code for humans. This is code for the browser; it is optimized for the browser. Separating the code for humans and the code for the machine means we don't have to choose between readability and speed.

Think of this like any compiler. The code that comes out of a compiler isn't intended for humans, it's intended for machines. The code that goes into the compiler is intended for humans. As a lover of readable code, this excites me.

At a glance, Svelte is a tool for writing component-based UIs with incredibly simple (read: maintainable) JavaScript. I'm not sure I'd put it in production yet, but I'm more excited to follow the development of Svelte than almost any other web technology right now.

🚀🎸🏎

There's more...

I'm writing a lot of articles these days, I run a podcast, and I've started sending out a newsletter digest about all of the awesome stories I'm hearing.

You can also follow me on Twitter, where I make silly memes and talk about being a developer.

Discussion (20)

Collapse
chrisachard profile image
Chris Achard

Nice post Jacob!

I don't know if you already know this, but if you want cool syntax highlighting on your code in DEV posts, then instead of just:



```
code
```


You can do:



```html
code
```


Or:



```javascript
code
```


:)

Collapse
absinthetized profile image
Matteo Nunziati

It is a certain number of weeks I'm looking at svelte. My only issue is: when a bundle like bootstrap-vue or a set of material design/bulma widgets will be out?
Then I will use it! It is the most sane thing I've seen on frontend after backbone.

Collapse
joelbonetr profile image
JoelBonetR

Why anyone would put vue inside a svelte project? It gives nothing extra from my point of view.
By the other part, don't mind on bootstrap as valid responsive/ui framework as it loads a considerable bunch of js and css (moreover it needs jQuery). It breaks the modularity on svelte or every SPA you could make.
In my opinion, Mustard UI could be a better approach: css only, lightweight and bootstrap 3.x like syntax. If you need some js plugin for giving some functionality that it's not on sapper/svelte neither on mustard, you can import it only wherever you need it, instead on load it across all entire project.

Regards

Collapse
alfiedarko profile image
Alfie Darko

Describing it as sane is very accurate

Collapse
jcameronjeff profile image
Jeff Cameron

Probably as soon as someone who wants it writes it an open sources it ;)

Collapse
luwes profile image
wesley luyten

Great writeup! Really like Svelte's approach but saying Svelte outputs vanilla JavaScript is not accurate I think. It still has a runtime, that's the svelte/internal etc in the compiled output code. That's a dependency. The same is true for Stencil. It's a tiny runtime for sure but it exists :)

Collapse
wrldwzrd89 profile image
Eric Ahnell

Interesting! Definitely something to keep an eye on.

Collapse
abduzido_dev profile image
Programador Abduzido

Amazing artcle! I loved how this workz, thks by the good news ;)

Collapse
Sloan, the sloth mascot
Comment deleted
Collapse
jacobherrington profile image
Jacob Herrington (he/him) Author

I'm sorry you don't like Svelte, but attacking people who use modern JS frameworks reveals that your opinion is probably just ignorance manifested.

Innovation tends to frustrate some people. 🤷‍♀️

Collapse
giorgosk profile image
Giorgos Kontopoulos 👀

Nice post, I like Svelte, never had a chance to use it production but why would you say "I'm not sure I'd put it in production" ? Is there any particular reason ?

Collapse
jacobherrington profile image
Jacob Herrington (he/him) Author

Mostly just because it's young. I tend to fall in the camp of stable stuff over novel stuff.

Collapse
blazephoenix profile image
Tanmay Naik

Do you think Svelte would find as much popularity and acceptance as a front-end framework as React? Or would it be more of a niche framework like Vue?

Collapse
jacobherrington profile image
Jacob Herrington (he/him) Author

I'm not sure. React will be around for a very long time due to the sheer volume of React code that has been written. Svelte seems like it might be a bit more niche, but I see as an evolution of the VDOM approach.

Collapse
ben profile image
Ben Halpern

Really nice

Collapse
jacobherrington profile image
Jacob Herrington (he/him) Author

quite

Collapse
gabuardi profile image
Josué Gabuardi

I have a little doubt... the way of how Svelte compile and export vanilla JS is not the same way than Angular do?

Collapse
klausbert profile image
Klausbert

Thanks Jacob for this heads-up.
Interesting (slender!) syntax... What about debugging?

Collapse
cristiadu profile image
Cristiano Faustino

The syntax looks sort of ugly I would say. Not that this makes any difference in the effectiveness of it, but still, haha.

Collapse
joelbonetr profile image
JoelBonetR • Edited

Well i find the syntax is very concise and everyone with knowledge on js and html could find a point on it. Can't say the same on angular for example...
div *ngIf="whatever=[thing]"

What's the asterisk? And the brackets? Is it an array? Why should I put a templating condition as html attribute?

Damn it's like blending html syntax with a dumb ass alien child.
I've been working with angular for a year and it feels weird. I'm testing svelte for a week and it feels so nice, automagic routing (file-system based) instead on declaring things on 493873places, easy syntax, strict compiler etc... Will say more when i take the hands on for a real project