As a web developer, if you haven’t been living in a nuclear bunker somewhere remote, you have definitely heard of Svelte. Why is this tool sweeping developers off of their feet? How did it become the most loved tool even in the presence of the framework giant, React. In this blog, we will take a deeper look into why and how Svelte has taken the hearts of many web developers.
What is Svelte?
Starting from the basics, the word svelte has a meaning that lies along these lines: elegant, thin, graceful, stylish.
Svelte is a UI framework that helps us build reusable and self-contained components in plain HTML, CSS and JavaScript. When you create a component, using the .svelte extension, all you need is to include your <script> tag, html tags like <div> enriched with additional features, and a locally scoped <style> tag to write your css just like the good old vanilla JS days (JS in HTML).
Svelte is also a compiler. It converts our declaratively written component code into highly optimized standalone vanilla JavaScript modules at build time. The major benefit this brings to the table is that we do not have to pay performance costs by shipping the framework logic to the browser, reducing the work it has to do and in return making execution time swift.
Most frameworks like ReactJS and VueJS interprets our declarative application code at runtime. This means that the browser has to do extra work to convert our declarative code into DOM (using VirtualDOM diffing) which is not free of performance costs.
Additionally, Svelte has a significantly small bundle size, as seen here. If you take a look at the package.json file of a Svelte project, it only contains devDependencies on application startup, having zero client-side dependencies!
Svelte Core Features
- No Virtual DOM
- Truly Reactive
- Write less code
No Virtual DOM
VirtualDOM is an in-memory virtual representation of our application logic, which is used to compare and sync with the “real” DOM of the browser. It is a concept implemented by libraries in JavaScript on top of browser APIs.
The major benefit vDOM brought at the time of its invention was that it was faster and easier to manipulate. So it was just fast in comparison with the “real” DOM.
While libraries like React use ReactDOM to achieve this reconciliation, Svelte takes a completely distinct route by removing the vDOM concept altogether.
Svelte simply compiles our code into tiny framework-less vanilla JS that manipulates the DOM directly, and it is still fast. These DOM manipulations are nothing but if(stateChanges) statements.
Here is a deeper explanation on how Svelte achieves this.
Truly Reactive
Svelte keeps the DOM in sync with our application state using Reactivity. This reactive nature of Svelte is supported out of the box , so we generally have less code to write in order for our app to reflect state changes (looking at you, useState 👀).
How does this work?
- Every time we assign to a variable that is used in our components’ markup, an invalidate function is called.
For demonstrating this, a simple function that increments a count variable looks like this in Svelte:
<script>
let count = 0;
function handleCount(){
count+=1;
}
</script>
<h1>Count is {count}</h1>
<button on:click={handleCount}>
Click me!
</button>
Svelte automatically detects that our component must reflect the changes of count and decorates our assignment statement with the invalidate function. Part of the compiled output will look something like this:
function instance($$self, $$props, $$invalidate) {
let count = 0;
function handleCount() {
$$invalidate(0, count += 1); // Here
}
return [count, handleCount];
}
The invalidate function simply tells the component to be aware of changes in the count variable.
For comparison purposes, here is what the same counter function would look like with React:
const Counter = () => {
const [count, setCount] = useState(0);
const handleCount = () => {
setCount(count+1);
}
return (
<>
<h1>{count}</h1>
<button onClick={handleCount}> Click Me! </button>
</>
)
}
— we are writing way too much code for such a simple functionality.
2. Derived State
Let’s assume we have variables in our components that are derived from some part of application state (this happens almost always). Every time our component re-renders these derived states are recalculated over and over again whether the state changed or not. In React, we use hooks like useMemo to avoid this exact situation. Talk about code buildup.
In Svelte, we declare derived states using $ as such:
<script>
let count = 0;
$: doublCount = count * 2; //Derived State
function handleCount(){
count+=1;
}
</script>
<h1>Count is {count}</h1>
<h2>
Double Count is {doubleCount}
</h2>
<button on:click={handleCount}>
Click me!
</button>
We are telling Svelte, here is a reactive value that depends on another reactive value and their values are bound. This is part of what the compiler outputs:
function instance($$self, $$props, $$invalidate) {
let doubleCount;
let count = 0;
function handleCount() {
$$invalidate(0, count += 1);
}
$$self.$$.update = () => {
if ($$self.$$.dirty & /*count*/ 1) { // Recalculation happens if count changed
$: $$invalidate(1, doubleCount = count * 2);
}
};
return [count, doubleCount, handleCount];
}
It simply wraps our condition in an if statement, and if our count changes we recalculate doubleCount.
Less Code
According to Rich Harris, creator of Svelte, the most efficient way to speed up your code is to get rid of it.
This feature is probably more obvious than the others. As seen on the counter example above, we write more code in React than in Svelte to achieve the same functionality.
Additionally, Svelte offers much more flexibility in our component markup by allowing multiple top level elements, as opposed to being constrained to return a single top-level element using fragment (<>) in case of React and <template> in case of Vue.
It also reduces boilerplate code when handling events in our components, for example a simple input handling situation would look like this:
<script>
let show = 'world';
</script>
<h1> Hello, {show}</h1>
<input bind:value={show} />
🤯
It seems that the only downside of using Svelte is its relatively small community, which is subject to change in the near future.
Some use cases for Svelte
- When developing apps with minimal complexity that does not require multiple plugins
- Suited for highly performant and interactive web applications
- Runs smoothly on low end devices that do not have high processing power
- Replacing the homepage of your app by Svelte for a faster load time and experience (Spotify does this)
- Great for developers who do not have a lot of experiences with JavaScript
A rough overview of Svelte Kit
“Svelte is to React as SvelteKit is to Next JS”
Svelte Kit is an opinionated web application framework that helps in structuring our Svelte code, and provides multiple functionalities to Svelte such as:
- Folder based routing
- Built in load functions for fetching data before the component runs
- SSR
- SEO Enhancement
- State Management
- Environment file handling
- Asset Handling
- Form Handling
- layout component for default applications layouts (footer, header, etc…) using <slot>
More reading here.
Conclusion
Svelte, with these core features at its heart, is a strong competitor to the already existing frameworks, and challenges our ways of thinking about modern web development strategies. It helps us build rich components with little to no complexity, with built in support for modern web concepts such as reactivity.
With its growing community, there is no doubt that the future for Svelte is bright.
Note: Throughout this blog, it would seem that I was bashing our beloved framework, React. Let it be known that it was just intended for comparison purposes. 💙