Svelte - The vanishing framework for frontend app development

Posted Feb 04, 2021

Anthony Gore
Author
Shanika Wickramasinghe
Research


Way back in 2012, developer Mike Taylor tweeted this:

"The solution to worrying about JavaScript library or framework size: include one less jpeg on your site."

Someone who read this tweet is Rich Harris, a graphics editor at the New York Times. As he saw it, 100kb of jpg is not the same as 100kb of JavaScript.

He reasoned that the cost of JavaScript frameworks isn't just the extra network traffic caused by downloading the framework. It's also the time spent by the JavaScript engine to parse and evaluate the script.

This line of thought led Rich to the idea of Svelte - an open-source JavaScript tool he would release in 2016 that would change how developers think about frontend app architecture.

What is Svelte? #

Just like the more popular React, Angular, and Vue, Svelte is a component-based JavaScript framework used for building dynamic web apps.

The thing about Svelte, though, is that it isn't really a framework - it could be more accurately described as a compiler.

This unique architecture allows Svelte to do a lot of heavy-lifting at build time and alleviates the problem of JavaScript slowing down pages.

As such, Svelte apps are arguably faster and lighter than those of status quo frameworks.

How Svelte works #

As with most JavaScript frameworks, Svelte apps are comprised of components, in other words, reusable blocks of code encapsulating HTML, CSS, and JavaScript, which are used to build the page content.

A Svelte component is defined in a .svelte file. This file looks just like an HTML file and will typically include a script tag for any JavaScript logic and a style tag for CSS

In this example, a JavaScript variable count is incremented every time a user clicks a button and gets interpolated on the page.

<!--App.svelte-->

<script>
let count = 0;

function handleClick () {
count += 1;
}
</script>

<style>
p {
font-weight: bold;
}
</style>

<button on:click={handleClick}>Increment</button>
<p>{ count }</p>

Once you've defined a Svelte component, you simply need to mount it to the page by indicating a target element - typically the document body.

// main.js

import App from './App.svelte';

var app = new App({
target: document.body
});

export default app;

You now have a functioning Svelte app, albeit a very basic one.

Note: It's easy to experiment with Svelte apps using the online Svelte REPL.

Svelte demo - count

Compiler architecture #

But wait, where does Svelte get included in the project?

Well, here's where we see Svelte's unique approach - there is no Svelte module to import or include, at least not in the app itself.

As a compiler library, Svelte is instead inserted into the build pipeline that you'll set up with Webpack, or maybe Rollup.

Once you run your build pipeline, the Svelte compiler will output your app as a JavaScript bundle.

Unlike React, Vue, or Angular, the outputted bundle does not include Svelte as a runtime dependency.

This means there's nothing distinctly "Svelte" about the outputted bundle - it's just vanilla JavaScript code!

Svelte features #

You may have noticed the syntax used by Svelte is very simple and looks like plain JavaScript.

However, Svelte does offer standard frontend framework features like reactive data and even state management.

Reactivity, in case you're unfamiliar with the term, means that JavaScript data is being tracked for changes and components will re-render in response.

In this Svelte component, for example, each time the user clicks the button, the handleClick method is called, and in turn, changes the value of count.

Since count is a reactive variable, changing it will trigger the page to re-render. In other words, the value of count will be reflected on the page.

But how does Svelte know to do this?

<!--App.svelte-->

<script>
let count = 0;

function handleClick () {
count += 1;
}
</script>

<style>
p {
font-weight: bold;
}
</style>

<button on:click={handleClick}>Increment</button>
<p>{ count }</p>

In other frameworks, you generally need to use an API method for this purpose. For example, if this were a Vue.js component, we'd we might use the ref API method to assign a reactive variable to count.

// App.vue

import { ref } from 'vue';

setup() {
let count = ref(0);

function handleClick () {
count.value += 1;
}

return { count };
}

Let's now take a look at the compiled code generated by Svelte to see how it achieves a similar effect.

As you can see, Svelte still requires extra code to make count reactive - the compiler has wrapped the statement in handleClick with a special method that tells the component that changing the value will require a re-render.

The difference is that Svelte adds this code itself in the compile step, a concept called "instrumenting".

let count = 0;

function handleClick() {
$$invalidate(0, count += 1);
}

Svelte and the virtual DOM #

Let's now move the discussion to how Svelte apps are rendered since there is no Svelte runtime.

Most modern JavaScript frameworks use a virtual DOM as part of their rendering layer.

What this means is that every time the app state changes and a re-render is required, a representation of how the page should look is generated in JavaScript. This is the "virtual" DOM.

This representation is then compared to how the page actually looks. Any differences can then be reconciled with DOM updates without having to completely re-render the page.

Image source: https://medium.com/@SilentHackz/at-the-heart-of-react-a9e03255c709

The virtual DOM is more efficient than a complete re-render but it still creates a performance burden that may be a bottleneck for complex pages.

Since Svelte compiles components at build time and has no runtime, it doesn't utilize a virtual DOM.

Instead, individual components track changes to their data and will simply re-render themselves as required.

By avoiding a runtime dependency, Svelte not only gains from a smaller bundle size but also gains from faster page rendering.

Uses of Svelte #

Now that you've got a sense of how Svelte works, you may be wondering how you might use Svelte out in the wild.

While Svelte's performance benefits would improve any web app, they're particularly ideal for...

  • Developing applications intended for limited internet connection
  • Low-power devices
  • And also apps with complex graphing or visualizations

This is why Svelte was the perfect choice for Stone, a point-of-sale device manufacturer that needed a highly-optimized UI for its low-memory and low-power point-of-sale device.

Advantages of Svelte #

By rethinking the architecture of JavaScript frontend apps, Svelte has accrued many advantages.

Let's quickly recap these.

Firstly, Svelte apps have a small build size since there's no framework to include.

Secondly, Svelte has superior performance by avoiding runtime bottlenecks like the virtual DOM.

Thirdly, Svelte has simple syntax and avoids boilerplate code since the compiler can instrument any necessary code in the build step.

Wrap up #

While the Svelte user community is still relatively small compared to status quo frameworks like React, Vue, and Angular, it is growing quickly.

Since the architecture pioneered by Svelte gives it a great advantage over these frameworks, will they adopt it as well? We'll have to wait and find out!

Thanks for reading and let us know in the comments if you've tried Svelte, or if you'd like to, and what you like most about it.

You might also like...


Did you enjoy this review? To help us bring you more just like it, consider sponsoring Dev Reviews on Patreon!

Become a Patron