SvelteJS: The next big UI framework
Marcus Stamström
Posted on September 29, 2019
SvelteJS: The next big UI framework
SvelteJS is the new UI framework on the block. Svelte is however very different in many aspects and especially in its mindset around how a UI framework should work and how it should solve the problems regarding writing a user interface. In this post, we will explore how to get started with SvelteJS by building a todo app (as always 😃 ). We will at the same time learn about what Svelte brings to the table and how it works.
TL:DR
SvelteJS is a compiler UI framework, some of its features are:
- Truly reactive framework
- Easy to learn
- Accessibility support
- Super fast and small bundle sizes
- Scoped CSS
- Fullfledge framework with a big toolbox to help develop faster.
Stay around and we will explore all this and more in this article.
What is Svelte?
Svelte is a framework for building user interfaces, like Vue or React. The key difference is that Svelte is a compiler, unlike React or Vue which runs in the browser. This key difference together with that Svelte is truly a reactive framework (which I would argue that React and Vue are not) opens a lot of opportunities that we will explore in this post.
In Svelte, we write code in the same declarative way as we do in for example React or VueJS. We do really notice that the UI framework is a compiler, which we also will see in the examples later on.
How do we get started?
The easiest way to get started is to download a boilerplate template from npx or start a project in codesandbox. To create a boilerplate template:
npx degit sveltejs/template my-todo-app
cd my-todo-app/
npm install
npm run dev
Easy as cake. Now we have a SvelteJS setup ready and can start coding. This project is setup with rollup, which is a bundler, like webpack but more minimalistic.
The boilerplate template with SvelteJS
At first glance, the project structure looks quite similar to what you would get from React or Vue from scratch.
Notice that we have a main.js
file, which basically does the same as for other UI frameworks, that is injecting the created js bundle into an HTML element. That's all about the setup, let us check out the code.
Svelte components
SvelteJS components are similar to HTML files, but with a lot of sugar on top. Javascript is typed in a script tag and CSS is typed in a style tag. The rest is interpreted as HTML. Here is the App.svelte component which comes with the template:
<script>
export let name;
</script>
<style>
h1 {
color: purple;
}
</style>
<h1>Hello {name}!</h1>
It prints the name variable which is passed in from main.js. So that’s the first thing we can see that is different syntactically. Props are those properties that are exported in the script tag.
Reactivity by assignment
But we want to create a todo app so let's start making changes. Let us start by adding an input field and connect that with a variable
Pretty similar to React or Vue, but with a lot less boilerplate. We have a todo variable which gets updated when the value in the input field is changed.
Notice that we are using the assignment operator. The assignment operator is a big part of SvelteJS reactivity system. When assigning a new value to a variable, that assignment will also tell SvelteJS that something has changed in the App and that Svelte needs to update the variable in the DOM in the end of the event loop. Yes, there is an event loop to batch DOM updates, which is good for minimizing repaints.
We can actually make this a little cleaner with the help of the SvelteJS two-way data binding directive.
And it still works like before. We are using the bind
directive to use both read and write operation for HTML elements. This also works for checkboxes and other kinds of inputs.
Let's continue coding and check how to iterate over arrays.
Now we have added the possibility to add todos to an array and display those added todos. There are some important observations in the newly added code:
the
${each}
command in the HTML iterates over an array, with the item as its first parameter and the index as its second parameter. Notice that we have to close the iteration with{/each}
. To use the index write{#each todos as (todo, index)}
on line 5 we reassign the array instead of using push, in SvelteJS, using operations like push will not trigger an update of that value. This is a very important observation, as we mentioned previously SvelteJS reactivity system is built around the use of the assignment operator. So we cant use operations that don't return the updated variable. Push returns the length of the array after adding a new item.
In React, VueJs and other frameworks we need to have a wrapping element for each component. In SvelteJS we don't need a wrapping element for each component, which helps avoid div nesting issues.
There is no
this
in the component. Since SvelteJS is a compiler, it doesn't have to apply all the rules that UI frameworks that run in the browser have to.
But we are not completely reactive yet
Now we have seen some examples of how reactivity works in SvelteJS. It works a bit different since the code is compiled at compile time and only run once in the browser. We have seen how we can have variables in the HTML and if we assign a new value to that variable, the DOM also updates. But what if we have a variable that depends on another variable. Let's consider this example:
let isDone = false;
const infoMessage = isDone ? 'You finished' : 'Keep going!!'
If we would change the isDone variable somewhere in the code, that would not recompute infoMessage. As we just mentioned, that is because the code only run once. Let's take another example with our todo app, which now has the possibility to set todos as done as well as filtering on remaining todos.
As we can see in this example, it's not reactive. I click the checkbox to hide buy groceries, but it's not disappearing. That's because our code only run once.
Svelte has come up with a solution for this problem, by "adding" a reactive command. We can add a $:
, which is valid javascript and is a labeled statement. It doesn't really do anything so Svelte uses this for reactivity. How that work is that the $:
is like a subscription and subscribes to the values in the expression. So if we revisit our example and do this change, then it should work.
With this change, our todo app is now reactive and filters out the done todos when selecting the checkbox.
How that works more exactly is that this code runs in topological order. Which means that filteredTodos
depend on onlyShowRemainingTodos
and filtreredTodos
will run after onlyShowRemainingTodos
has changed. This means we can also have reactive values that depend on other reactive values. We could, for example, have a variable that depends on filtered todos:
let todos = [
{id: 0, text: 'Buy groceries', isDone: false},
{id: 1, text: 'Go to the Gym', isDone: false}];
let onlyShowRemainingTodos = false;
$: filteredTodos = onlyShowRemainingTodos ?
todos.filter(x => !x.isDone) : todos;
$: numberOfFilteredTodos = filteredTodos.length;
Scoped CSS
All CSS in the style tag is by default scoped, which is really awesome. This means we don't have to worry about complicated naming schemes like BEM or using pre-processors. You could still use BEM or pre-processors if you want to, but there aren't as many benefits when the global CSS issues are already solved. What scoped CSS gives us, is that the CSS is specific for each component. So we can have the same CSS class in 2 different components without having name collision.
As we can see in this example, svelte hashes our CSS to be specific for the App component, thereby making it scoped. Also notice that I added a CSS class that is not used in the HTML. That CSS class will not be included by Svelte in the CSS bundle, since it's not used anywhere.
Other key features
So far we have covered some of the features in SvelteJS, there are however a lot more. We will touch on some more features briefly, but we won't go through all of them in this article. For complete code example and to see all the features, I encourage you to visit svelte.dev
Performance
In the compile process, Svelte compiles our svelte components into high-performance imperative javascript code. This makes our code very fast to run for the browser. As I mentioned, our code only runs once and not every time some state changes, which is a huge performance benefit. When Svelte turns our declarative code into high-performance imperative code, it also disappears from our bundle, since all the logic for updating the DOM is done in the build process and what's left of SvelteJS in our bundle is just some helper functions.
Okay, so we have small bundles which mean faster loading time and faster time to first interactivity and our app is faster due to the imperative code. What not to like 😃
No virtual DOM
With Svelte, all the computation for working out the most efficient way of reacting to a state change is done beforehand. With this way of thinking, we don't need a virtual DOM. The virtual DOM can now actually be seen as a bottleneck for performance. Svelte does not use a virtual DOM and is much faster because of it.
Easy to learn
Unlike most other frameworks, Svelte components look like HTML with javascript and CSS put in script and style tags. This makes the code more familiar to those not experienced with any UI frameworks. For those who are already using UI frameworks, its very easy to get started as well.
There is also very little boilerplate, which makes it very easy to read and understand. This is a big selling point when learning a new framework, it lets you do what you are supposed to do, without typing much framework specific code.
Fullfledge framework
That SvelteJS is a compiler also gives us an advantage when it comes to which features that Svelte can include in the framework. It gives Svelte the advantage of including a lot of features, but its only the features that you use in the app that will be included in the bundle. The rest of the feature will be tree shaken away. That is really great, it gives us a very big toolbox to choose from, making development easier, without having to pay for the features we aren't using.
Conclusion
I think Svelte is a really great framework. It's easy to learn, fast and has a lot of usable and cool features. It gives a different mindset about how to think about UI frameworks in terms of reactivity and what a UI framework should help to solve. It feels easy to start working with Svelte because of their big toolbox and we don't have to worry as much about performance. I think Svelte will become one of the big UI frameworks in the future and I hope I have inspired you to give it a try, either by following my steps and setting up your own project or go svelte.dev and try some of the tutorial steps.
Thanks for reading !!
Posted on September 29, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.