When I first saw Svelte, the first thing that struck me was that it reminded me a lot of Vue. As I dug into a bit more, I realized that despite many similarities, there were also some big differences.
What follows is not the perspective of either a Vue or a Svelte expert. I build React sites at my day job. But I like a lot of what I see with both of these frameworks and I thought I’d share some of what I’ve found out about them.
Template Syntax
Both Svelte and Vue use HTML-based template syntax. The most basic examples from their respective docs looks very similar.
Here’s Vue:
<div id="app">
{{ message }}
</div>
And here’s Svelte:
<h1>Hello {{name}}!</h1>
Pretty similar, right? Other template syntax differs, however. Here’s a loop in a Vue template:
<div id="app-4">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
And now in Svelte:
<h1>Cats of YouTube</h1>
<ul>
{{#each cats as cat}}
<li><a target='_blank' href='{{cat.video}}'>{{cat.name}}</a></li>
{{/each}}
</ul>
If you look at the Vue syntax and think it looks just like AngularJS, you’d be right. In the case of Svelte, however, the curly braces are actually JavaScript expressions. So, they look similar, but work a bit differently. The differences are not so great that they add up to much, though. If you understand one, you’ll quickly grasp the other.
One thing I should note here is that Vue also supports JSX, which has been popularized by React. Svelte does not. And as far as I can tell, JSX is not that popular in the Vue community. It’s an option, though.
Single File Components
Both Vue and Svelte have the concept of single file components. This means that the HTML, JavaScript and CSS for a given component lives in a single file. It’s a simple, but powerful, idea and one that makes working with these two frameworks easier than some of the alternatives.
Here’s an example of a single file component in Vue:
<template>
<section class="container">
<div>
<app-logo/>
<h1 class="title">
Demo
</h1>
<h2 class="subtitle">
My project
</h2>
</div>
</section>
</template>
<script>
import AppLogo from '~/components/AppLogo.vue'
export default {
components: {
AppLogo
}
}
</script>
<style>
.container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
</style>
You can see we have our template, script and style tags all in one place, and the CSS is automatically scoped to that component. Now let’s take a look at an example from Svelte:
<:Head>
<title>My project</title>
</:Head>
<Layout page='home'>
<h1>Hi there</h1>
<p><strong>Boom!</strong></p>
</Layout>
<script>
import Layout from './_components/Layout.html';
export default {
components: {
Layout
}
};
</script>
<style>
h1, figure, p {
text-align: center;
margin: 0 auto;
}
p {
margin: 1em auto;
}
@media (min-width: 480px) {
h1 {
font-size: 4em;
}
}
</style>
Looks pretty similar, right? You may notice in the Svelte file above that it has a <:Head>
tag. That’s a built in component that lets you add meta tags to the <head>
of your document. Vue doesn’t have anything similar included by default, but there are a couple libraries called vue-head and vue-meta that you can use to acheive the same result. If we wanted to add the meta information to our Vue component using vue-meta
, we’d need to update the script section to something like this:
import AppLogo from '~/components/AppLogo.vue'
export default {
components: {
AppLogo
},
metaInfo: {
title: 'My project',
}
}
A final point here is that the HTML and CSS in these examples are no different than what you are used to working with outside of JavaScript frameworks. This is in contrast to React, which as mentioned previously, uses JSX.
I’ve focused on the similar template syntax and single file components because if you’re building an app, you’re going to be spending a lot of time with these features. Before we move on, however, there are a few other similarities I’d like to briefly mention.
Both have reactive programming models (if the data changes, the view automatically updates). Both also have computed properties, lifecycle hooks, and custom methods. If you poke around in the docs for each of these frameworks, you’ll notice other common approaches and concepts...but there are also some major differences.
The Magical Disappearing UI Framework
Without question, the biggest difference is that Svelte is a compiled framework. From the docs:
…rather than interpreting your application code at run time, your app is converted into ideal JavaScript at build time. That means you don't pay the performance cost of the framework's abstractions, or incur a penalty when your app first loads.
The result of this is that Svelte apps will end up considerably smaller than those using Vue. To demonstrate this, I spun up the most basic Vue app possible using Nuxt.js. It's a framework that has all the stuff you’d need to build a server-rendered Vue application with routing and state management. In fact, some of the code snippets above were adapted from the default Nuxt.js app.
Although much newer, Svelte has a similar framework called Sapper. It also has everything you need to build a server-rendered app with routing and state management. I’m not super familiar with the internals of these two frameworks, so perhaps Nuxt.js has something cool that Sapper doesn’t, but this was as close to an apples-to-apples comparison of a real app as I could get.
Here are the results for production builds:
Framework | Total JS size (minified, not gzipped) |
---|---|
Nuxt.js | 182.1 KB |
Sapper | 11.4 KB 💥 |
Some comments about these numbers…they include all the JS files each framework loaded on the home page (both use code splitting). The Sapper number actually includes additional files that we probably should exclude to give a fairer comparison. There are two routes set up in Sapper that don’t exist in the Nuxt.js example (resulting in two additional files). If we remove those, then Sapper comes in at about 8KB. I mean, seriously…8KB! That’s incredible!
This shows up in performance benchmarks, as well. Below is a screenshot showing the start up metrics for Vue and Svelte from a popular benchmarking tool. In the chart below, smaller numbers === faster performance.
Svelte is very fast, even faster than the vanilla JS example in two of the benchmarks. Svelte is hard to beat in this regard. I’m not saying Vue is slow — far from it. But if fast page loads are a priority on your project, Svelte is a framework to seriously consider.
The Progressive Framework
Another difference between these two frameworks is that Vue can be used as a jQuery replacement in a way that Svelte can’t. Sarah Drasner has done a great write up on this, so I won’t go into it further, but it highlights a versatility that Svelte — and many other frameworks — don't have.
And Finally…
The last difference I’ll note is that Vue has a much larger community and ecosystem. There are a lot of great Vue training courses available to help get you started and the third party libraries can speed up development.
That said, these are both great frameworks. Vue certainly deserves all the attention it’s received over the past year, and I hope you agree that Svelte should definitely be getting more attention that it currently does. It’s a young framework, so no doubt big things are ahead.
If you’ve enjoyed this post, sign up for my weekly newsletter. I curate the best JavaScript writing from around the web and deliver it to readers every Thursday. The sign up form is right below this article.
Until next time, happy coding…