Thursday, April 22, 2021

Vue 3 update (July 2021): This article was originally based on my experience with Vue 2. Vue 3 narrows the differences. I have added "Vue 3" comments below where applicable.

I have been using Vue.js for client side browser stuff for a few years and I am very happy with it. However, I have been curious about Svelte for a while, and as I had an idea for a new project where Svelte might be a better fit than Vue, I decided to take a closer look.

Also, I have a number of ongoing projects in Vue 2, and with the significant breaking changes in Vue 3, now might be a good time to explore alternatives, as moving to a different framework might not be much more work than the Vue upgrades that I am facing anyway.

I recently did a small SPA (Danish budget calculator) based on Vue, and figured that it would be a nice test to convert this to Svelte. I copied the .vue files to a new Svelte project, renamed the files .svelte, and then manually massaged them into the Svelte syntax. The source code (Vue + Svelte) is available at: https://github.com/jesperhoy/Mit-Budget.dk

Minified and gzipped, the javascript for the original Vue version (https://mit-budget.dk/vue) is 9.2kb + 23.6kB Vue runtime = 32.8kB total. The Svelte version (https://mit-budget.dk/svelte) is 19.2kB.

The following is based on my experience converting this project:

In favor of Svelte

  • No runtime
    The Vue runtime is not that big, but still significant for smaller "apps".
    Consider, for example, the code to validate a simple contact form. Here the Vue runtime would be disproportional huge for the functionality provided.
    Small Svelte apps compile to just a few kBs and need no runtime.
    Vue 3: The Vue "runtime" runtime (no template compiler) grew from 24.8kB (gzipped) to 30.4kB (+23%) in Vue 3 (+1 for Svelte).

  • No this... this... this...
    Unlike Vue, in Svelte you don't need to prefix everything with this. in code blocks to get at anything else within the same component.
    This is also a constant cause of errors in Vue for me. Template in-line script does not need this, and so whenever you move code between template and code blocks and forget to fix this - boom.
    A big part of the project conversion was removing this. all over the place.
    Vue 3: The new Vue 3 composition API "setup" function solves this issue (+1 for Vue 3).

  • Straight forward, readable javascript
    Unlike Vue where everything in an app or component must be expressed as one big object.
    The Svelte way, where you declare variables (let x=...) and write functions (function xyz(...) {...}) in the root of a <script> tag - just like good old fashioned straight forward javascript - is just easier to work with and much easier to read.
    Vue 3: The new Vue 3 composition API "setup" function solves this issue (+1 for Vue 3).

  • Zero indentation / no curly brace mess
    Vue requires at least 2-3 levels of indentation before you write any actual program code. Keeping track of all those curly braces can be a real pain - especially for larger component files.
    Reflecting back on my time with Vue, I often found myself moving functions to a separate global .js file, just to avoid the curly brace mess. This is not a problem in Svelte, and so I find it easier to keep code where it belongs.

    Vue:

    <script>
    export default {
        methods: {
            MyFunction() {
                actual program code...
    

    Svelte:

    <script>
    actual program code...
    

    Vue 3: The new Vue 3 <script setup> feature (experimental) solves this (when using build tools only) (+1 for Vue 3).

  • Less boilerplate
    No <template>...</template>, no export default {...}, no data: {...}, no methods: {...}, etc.
    Vue 3: The new Vue 3 Composition API "setup" function improves this (+1 for Vue 3).

  • Two-way property binding
    In Svelte this is simple (bind:propname={variable}) which I found very convenient. In Vue.js it requires emitting events and more code.

  • Raw html rendering not tied to an HTML element
    Vue: <div v-html="HtmlString"></div>
    Svelte: {@html HtmlString}

  • Multiple root elements in components - a.k.a. "fragments"
    Possible in Svelt - not possible in Vue.
    Vue 3: This is also possible in Vue 3 (+1 for Vue 3).

  • Better VS Code extension / integration
    Using the "default" VS Code extensions (Vetur / Svelte for VS Code), it appears that I am getting more assistance with Svelte files - like catching undefined variables inside {...} blocks in the HTML.

  • Performance (?)
    Svelte is supposedly faster at updating the display because it doesn't use a "virtual DOM" (like Vue, React, Angular, etc.).
    I never had any problems with display update speed in Vue (or Svelte) so I can neither confirm nor deny.
    However, I do imagine this being a real advantage when coding for low powered devices.

In favor of Vue

  • Client side template compilation
    Smaller Vue "apps" can be included as source on a web-page directly without any pre-processing. Svelte apps cannot.
    For web-pages (not "apps") where you need just a little bit of reactivity (like order forms), this is perfect. No need to run a compiler/bundler etc.
    Another cool thing about this is, that it allows you to put dynamically server side rendered html/data directly inside a Vue template, mixing server and client side processing very nicely.
    I have personally used this quite a lot, and the beauty of this was exactly the thing got me started with Vue in the first place.
    Vue 3:
    It seems like Vue is moving away from client side template compilation - becoming less "progressive".
    The full runtime (with template compiler) grew from 35.7KB (gzipped) to 45.4KB (+27%).
    Some new features are only available when using build tools (like <script setup>).
    It is no longer possible to register components globally (replaced by app level registration) - making storing components in separate .js files more complex.
    The release of Petite-Vue seems a strong indicator of this as well.
    (+1 for Svelte)

  • Better browser DevTools
    Browser (Chrome/Firefox) "DevTools" are available for both Svelte and Vue.js, and with both tools, you can browse the live component hierarchy and see and change component property values. However, that's it for the Svelte DevTools. The Vue.js DevTools also includes "Vuex" (for state), Events, Routing and Performance. And the Vue DevTools seem more stable.

  • Ecosystem
    Vue is more established and enjoys a much larger selection of component libraries, StackOverflow answers, blogs posts, etc.

  • Smaller bundle size for large apps (?)
    Svelte apps start out small (no runtime), but they grow faster than Vue apps. This became quite obvious as I was progressing through the project conversion.
    It would seem that at some point (around "medium sized" app), compiled Svelte apps could become bigger than Vue apps including runtime.

Tie

  • Single file components (SFC)
    Both have this - which is just awesome.

  • Great documentation web-sites
    Both have this.

  • Reactivity
    In Vue, anything under data and props is reactive - including object and array children. And any code (anywhere) that reads those items will automatically re-run when the items are updated. This makes it pretty simple to work with.
    In Svelte you need to be more explicit about when you want reactivity. Variables declared at a script block root are reactive and so are explicitly defined "stores". But code that read these values will only be re-run automatically if the code is in a statement prefixed with a $: label. I haven't encountered any real problems/challenges related to this with Svelte so far, but I imagine that it at the very least requires a different way of thinking about reactivity.
    This Svelte $: label takes a little getting used to, but is kinda cool once you do get it. It works similar to the Vue computed and watch blocks, but different.

Conclusion

Someone asked the question "Does this code spark joy?"
Back when I discovered Vue - this really was a game changer for me - and it did spark a lot of joy :-)
I imagine many programmers feel this way when they first "get" the reactive UI model (be it in Vue, React, Angluar, etc.).

Vue still sparks joy, but Svelte does so even more :-)

I really like the simpler and terser Svelte syntax - including the "missing" this. prefixes and curly braces.

I also really like not having to distribute a runtime.

Svelte will be my primary frontend tool going forward.

Vue 3:

Vue 3 narrows the differences significantly, but I still prefer the Svelte syntax (simpler and cleaner IMHO), having no runtime, and the superior performance. I also find that the Svelte build system is simpler and easier to work with.

Having a closer look at Vue 3 also confirmed the premise of this blog post - that the breaking changes in Vue 3 are indeed signicant enough that moving a Vue 2 project to Svelte is not much more work than upgrading it to Vue 3.

So I won't be using Vue 3 itself - but Petite-Vue (a Vue 3 off-spring) is perfect for "progressive" scenarios - enhancing server rendered pages client side.

You could say that Petite-Vue was the missing piece of my puzzle, because quite often, I just need a tiny bit of client side reactivity, and so it doesn't make sense to add a build system to the equation. I had been considering Alpine.js for this, but Petite-Vue is even smaller and I already know the syntax from Vue.

So my plan now, is to use Petite-Vue for simple "progressive" stuff, and Svelte for everything else.

Share: Twitter /  Facebook /  LinkedIn    
Copyright © 2006-2021 Jesper G. Høy