My thoughts on Svelte - The magical disappearing UI framework

in #programming6 years ago

A few months ago I've made a Mastodon account (that I haven't really been using since I tried to stay off social media and focus on work for a while, and I also prefer the fully decentralized Secure Scuttlebutt to the federated Mastodon) and while I was checking out Mastodon apps I saw one written in a curious framework called Svelte I hadn't heard about before.

Screenshot_2019-02-23 Svelte.png

It looked almost exactly like Vue, but was even easier to use and had additional properties that were really nice, so I decided to write my next web app using Svelte to try it out (after some initial smaller experiments of course).

3888 lines of code later my new web app project iftool was born and I started to like Svelte a lot, even though it's not quite as good as my personal favorite, ClojureScript with the Reagent framework (based on React), which is IMHO the best way to write client side web apps today, where best is defined as having all the modern features you'd want with almost zero boilerplate so you can concentrate on writing your app and not using the framework. It easily beats all the popular frameworks in my experience.

Svelte comes pretty close to that, but I'd still say ClojureScript + Reagent is the winner in the comparison. Bearing in mind however that I only know jQuery, React, Vue, Angular, Reagent and now Svelte, so maybe there is something that is even better that I never heard of because it's not popular and never appeared on my radar.

Anyhow, Svelte 3 is just around the corner and the beta version can already be used. And from what I've seen, Svelte 3 has the potential to beat even Reagent, to become something that is so much better than everything else (while being unbelievably easy to learn and use) that it's a real game changer.

Here's how you write a simple counter component in Svelte 3, just a paragraph displaying a number and three buttons to increase, decrease and reset the number:

svelte_counter.png

<div class="counter">
    <p>Count: {count}</p>
    <button on:click={() => count += 1}>+</button>
    <button on:click={() => count -= 1}>-</button>
    <button on:click={() => count = 0}>Reset</button>
</div>

<script>
    let count = 0;
</script>

<style>
    .counter {
        background: silver;
        padding: 5px;
    }
</style>

Save that to a Counter.svelte file and you've got a component ready to be used.

And just as with ClojureScript & Reagent, there is no boilerplate! Just the absolute minimum code necessary to do what you want. And you can export this as a custom element if you like. Svelte compiles away the framework, so you can use Svelte components wherever you want, in React/Vue/YourFavoriteFramework apps, in vanilla JS apps, doesn't matter. The overhead it adds is tiny so apps written completely in Svelte tend to be multiple times smaller (and also faster since it doesn't use virtual dom among other things) than React, Angular and Vue apps.

The Svelte 2 version of this example component would be:

<div class="counter">
    <p>Count: {count}</p>
    <button on:click="set({count: count + 1})">+</button>
    <button on:click="set({count: count - 1})">-</button>
    <button on:click="set({count: 0})">Reset</button>
</div>

<script>
    export default {
        data() {
            return {
                count: 0
            }
        }
    }
</script>

<style>
    .counter {
        background: silver;
        padding: 5px;
    }
</style>

The ClojureScript + Reagent version (in Reagent, a component is just a normal Clojure function):

(defn counter []
  (let [count (reagent/atom 0)]
    (fn []
      [:div {:style {:background "silver"
                     :padding 5}
       [:p "Count: " @count " times"]
       [:button {:on-click (fn [] (swap! count #(+ % 1)))} "+"]
       [:button {:on-click (fn [] (swap! count #(- % 1)))} "-"]
       [:button {:on-click (fn [] (reset! count 0))} "Reset"]])))

So about the same amount of code as Svelte 3, the ClojureScript version looks more concise but that's just because Lisp syntax is very concise, it's not really less work. Svelte 3 however beats that by having these nice properties :

  • You can write plain HTML and CSS in your components, no need to use special syntax for it
  • Plain JavaScript, super easy to get started, no complicated build tooling, so more people can contribute to your project
  • Svelte components can be exported as custom elements, although that doesn't give you any additional features so using a Svelte component is better than a custom element (no need for polyfills) unless you really need one

The example code I gave was of course very basic and there are many more advanced features in Svelte, but even those are extremely simple to use without any boilerplate in Svelte 3. But I won't go into that here, you can check it out yourself if you're interested :)

Well alright, one more neat thing, await blocks:

<script>
    const promise = new Promise(resolve => {
        setTimeout(() => resolve(42), 2000);
    });
</script>

{#await promise}
    <p>The answer to life, the universe and everything...</p>
{:then answer}
    <p>is {answer}</p>
{:catch error}
    <p>And I would have gotten away with it too, if it weren't for you meddling kids: {error}</p>
{/await}

I for one might make the switch to Svelte for good once version 3 is released. I'll miss writing Lisp code, but I try not to get too attached to things and instead use whatever tool is best for the job at hand.

Interesting aside, Svelte was created by Rich Harris, a journalist from The New York Times, while he was working for The Guardian. Not exactly where you normally expect the next big thing in web development to come from, but apparently the big magazines now have a bunch of "JavaScript journalists" working there who create interactive visuals for big and special articles. Rich talks about that in the Podcast I link to below. That's also why Svelte components can be so easily embedded in existing apps without adding a huge dependency to them, it was made for that. Rich also created degit, which lets you use any Github project as a template, and rollup, which is comparable to webpack and parcel and what Svelte uses by default.

Note: The Svelte creator advises you not to use Svelte 2 for new projects since Svelte 3 is a big change, so it's better to wait for it. I did it anyhow, because I didn't know, although I probably wouldn't have cared anyhow, I don't fear massive rewrites, can lead to better code because you know what you're doing when you've already done it and probably can think of a few things you would have done differently had you only known better.

Links:

Sort:  

Nice to see someone reviewing svelte. I also experiment a bit with svelte before svelte 3 (check my articles 😉).
Here is some interesting ongoing prototype of svelte that might interest you:
https://github.com/Rich-Harris/svelte-gl
https://github.com/halfnelson/svelte-native

Thanks for the links, Rich talked a bit about svelte-gl in the podcast. I did see svelte-native, but haven't looked into it yet (or nativescript in general), but if it becomes usable in the next few months I might use it in my iftool project to export games you create as native apps, my current plan was to use Flutter but being able to use Svelte for both the web app and the mobile app would of course mean having to maintain less code.

I can vouch for Svelte. It's fantastic, I wouldn't call it a framework per se, it's more of a UI library. I built an app for a client a year ago to give it a try and it was nice to use.

Have you tried Imba? The performance of it is impressive. Similar to Svelte in that it compiles down to native not overly magical Javascript either.

Having said that, I primarily work using Aurelia (disclaimer I am on the core team for Aurelia). It's not a library, it's a fully featured Javascript framework which is suited to LOB apps. I've got a few open source Steem apps coming out built with Aurelia shortly.

Posted using Partiko Android

I think neither library nor framework really fit. A library is something you import, that becomes part of your project, but Svelte's main selling point is that it's compiled away and "magically disappears". In combination with rollup it even does tree shaking for your JS and CSS, anything to reduce code size so that it's as small as possible to embed. The most correct term would probably be compiler, but that would just confuse people :) They'd start comparing it to TypeScript instead of Vue and React then.

I did try Imba out a while ago when I saw Scrimba on Hacker News, looked really neat, especially if you come from a Python background. But it wasn't enough to pull me away from Reagent + ClojureScript :)

With Reagent I really thought that's it, you cannot possibly do better, it removed as much boilerplate as is possible and I strongly believe in the principle that simple things should be simple to do, only add as much complexity as you need, which is what attracted me to Vue before I found Reagent. You can start out with Vue with just four lines of code, you don't need to use templates and components, but you can add as much complexity as you need when your project grows. The problem with ClojureScript + Reagent is that having to use Google's Closure Compiler has it's drawbacks and ClojureScript apps are huge because you've got a huge runtime to bundle with your app, so Svelte 3 has very compelling advantages there.

Aurelia I haven't heard about before, I'll check it out, thanks for mentioning it! :)

Hello @crypticwyrm! This is a friendly reminder that you have 3000 Partiko Points unclaimed in your Partiko account!

Partiko is a fast and beautiful mobile app for Steem, and it’s the most popular Steem mobile app out there! Download Partiko using the link below and login using SteemConnect to claim your 3000 Partiko points! You can easily convert them into Steem token!

https://partiko.app/referral/partiko

Congratulations @crypticwyrm! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Do not miss the last post from @steemitboard:

The Steem blockchain survived its first virus plague!
Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Nice article.
Maybe for the clojurescript counter exemple, the code can be more concise since you use javascript syntactic sugar too, no ?

(defn counter []
       (let [count (reagent/atom 0)]
         (fn []
           [:div {:style {:background "silver"
                          :padding 5}
                  [:p "Count: " @count " times"]
                  [:button {:on-click #(swap! count inc)} "+"]
                  [:button {:on-click #(swap! count dec)} "-"]
                  [:button {:on-click #(reset! count 0)} "Reset"]}])))