Swizec Teller - a geek with a hatswizec.com

Senior Mindset Book

Get promoted, earn a bigger salary, work for top companies

Senior Engineer Mindset cover
Learn more

    Svelte takes the best of React and the best of Vue to make something awesome

    Yesterday I tried Svelte to see what all the fuss is about. Version 3.0.0 came out recently and it smells like Svelte is ready for the big time.

    You can watch the livestream here 👇

    Created by @rich_harris, Svelte's unique idea is that there's no runtime. The framework compiles itself away to become vanilla JavaScript and create the smallest bundles you ever did see.

    Plus a few features to make development absolutely painless:

    • plain JavaScript in every file
    • plain CSS automatically scoped to components
    • plain HTML ... with some additions
    • no state management

    You can use plain HTML. You need the extensions to interact with Svelte and your code. Such is life.

    Building with Svelte feels like magic. Lemme show you 👇

    Building a Marvel movie timeline with Svelte

    We built a Marvel Movie timeline; 22 movies sorted by their timeline inside the Marvel Cinematic Universe. The AMC website helped out with a list coz I had no idea there were so many Marvel movies 😅

    Click 👆 to try it in action. Total JavaScript size just 17.2KB, or 7.2KB when compressed for transfer.

    That still sounds like a lot for this app, but it's less than React where you some 40KB goes just to React itself. The CSS compiled into a 1KB file with random classes for scoping. There's nothing else.

    App loads fast and works fast 👌

    You can see the full code on GitHub. Importing the repo into CodeSandbox didn't quite work and I'm not sure why.

    Best way to start a new Svelte project is with the CLI

    $ npx degit sveltejs/template my-svelte-project $ cd my-svelte-project $ yarn install $ yarn dev

    That creates a new Hello World project in my-svelte-project and runs the dev server. Go to localhost:5000 and start hacking. Every change triggers a page reload so you can see what you're doing.

    I didn't have to install anything new to make the above commands work 🤷‍♂️

    A Svelte component

    Svelte components live in .svelte files, split into 3 sections:

    1. JavaScript inside <script> tags
    2. CSS inside <style> tags
    3. HTML at the bottom

    Our App.svelte component looks like this.

    // src/App.svelte
        <script>
          // import other components
          import MarvelMovies from "./MarvelMovies.js";
          import Movie from "./Movie.svelte";
          import Header from "./Header.svelte";
          import Footer from "./Footer.svelte";
    
          // this is automatically reactive
          let index = 0;
    
          // assigning new values in functions triggers re-renders
          function nextMovie() {
            index = (index + 1) % MarvelMovies.length;
          }
    
          function prevMovie() {
            index = index - 1;
            if (index < 0) {
              index = MarvelMovies.length - 1;
            }
          }
        </script>
    
        <style>
          // all of this gets scoped to your component
          .grid-container {
            display: grid;
            grid-template-columns: 0.1fr 2.9fr 0.1fr;
            grid-template-rows: 0.1fr 2.8fr 0.1fr;
            grid-template-areas: "h1 h2 h3" "b1 b2 b3" "f1 f2 f3";
          }
    
          button {
            cursor: pointer;
          }
        </style>
    
        // free floating HTML is kinda neat
        <div class="grid-container">
          <Header />
    
          <button on:click={prevMovie} style="grid-area:b1">👈</button>
    
          <Movie {...MarvelMovies[index]} />
    
          <button on:click={nextMovie} style="grid-area:b3">👉</button>
    
          <Footer />
        </div>
    

    You might wanna install the Svelte plugin for VSCode to have proper syntax highlighting, Prettier support, and all the rest. The plugin did cause some weird issues while I was streaming, but who knows what that was.

    A few interesting things to note about App.svelte:

    • You can import .svelte components just like normal JavaScript
    • Every let variable becomes reactive by default
    • Assigning new values in functions triggers re-renders. No need to think about any of that
    • Your CSS is scoped to your component so there's no bleed-over
    • Your HTML free-floats at the bottom
    • Just like in JSX, Svelte components become HTML-like elements
    • Dynamic values go in curly braces, {}, same as JSX

    My favorite way to use custom components and add dynamic values to HTML. Vue's approach never quite made sense to me 😇

    A Svelte component with props

    Where I think Svelte really shines is building components for re-use. Like the <Movie /> component we used above to render the Movie view.

    // src/Movie.svelte
    
        <script>
          export let title;
          export let description;
          export let image;
          export let yearOut;
        </script>
    
        <style>
          .main {
            grid-area: b2;
    
            display: grid;
            grid-template-columns: 1fr;
            grid-template-rows: 0.1fr 400px 1.1fr;
            grid-template-areas: "title" "thumbnail" "description";
          }
    
          h2 {
            text-align: center;
            grid-area: title;
          }
    
          img {
            max-height: 100%;
            max-width: 640px;
            display: block;
          }
    
          .thumbnail {
            grid-area: thumbnail;
            display: flex;
            justify-content: center;
            align-items: center;
          }
    
          p {
            grid-area: description;
            padding: 0 1em;
          }
        </style>
    
        <div class="main">
          <h2>{title}</h2>
    
          <div class="thumbnail">
            <img src={image} alt={`${title} movie thumbnail`} />
          </div>
    
          <p>{description}</p>
    
        </div>
    

    Yep it's mostly CSS.

    You declare props by exporting let variables. Use them just like you would props in React 👉 <Movie title="Iron Man" description="..." />.

    Because our Movie props come from a variable, we used a spread and that worked too. <Movie {...MarvelMovies[index]} />.

    Notice that my CSS is very sloppy.

    I'm redefining h2, img, and p tags and yet it's totally fine. Svelte scopes it all to the <Movie> component.

    Whatever CSS you write here affects this file/component only and that's neat.

    Plus there was no boilerplate at all to get props working, reactive, and passed into the template. To be fair, the same React component looks like this:

    // <Movie> as React
    const Style = styled.div`
      grid-area: b2;
    
      display: grid;
      grid-template-columns: 1fr;
      grid-template-rows: 0.1fr 400px 1.1fr;
      grid-template-areas: "title" "thumbnail" "description";
    
      h2 {
        text-align: center;
        grid-area: title;
      }
    
      img {
        max-height: 100%;
        max-width: 640px;
        display: block;
      }
    
      .thumbnail {
        grid-area: thumbnail;
        display: flex;
        justify-content: center;
        align-items: center;
      }
    
      p {
        grid-area: description;
        padding: 0 1em;
      }
    `
    
    const Movie = ({ title, description, image, yearOut }) => (
      <Style>
        <h2>{title}</h2>
    
        <div class="thumbnail">
          <img src={image} alt={`${title} movie thumbnail`} />
        </div>
    
        <p>{description}</p>
      </Style>
    )
    

    Which isn't so bad either 🤔

    Svelte's reactivity

    Where Svelte shines is its reactivity. Look at all the state management for our app

    // this is automatically reactive
    let index = 0
    
    // assigning new values in functions triggers re-renders
    function nextMovie() {
      index = (index + 1) % MarvelMovies.length
    }
    
    function prevMovie() {
      index = index - 1
      if (index < 0) {
        index = MarvelMovies.length - 1
      }
    }
    

    Define a variable, index, change it inside methods. When its value changes, the component re-renders.

    😍

    As far as I understand, Svelte is smart enough to re-render only the HTML nodes that rely on the index variable. Sort of like what you can achieve with MobX and React if you're super careful.

    This does seem easier than React's setState. Less to think about.

    However, reactivity can come to bite you in the butt with more complex apps. Sometimes it leads to an effect like screen tearing where parts of the UI update before everything is ready.

    Imagine if instead of changing index, each button click changed title, image, and description separately. You might get each part of the UI updating on its own without waiting for all 3 to finish changing.

    For that, Svelte comes with a built-in dispatcher. I haven't used it, but looks like it gives you functionality similar to Redux.

    Svelte's event handling

    Another neat Svelte feature is the event handling.

    Svelte uses what I believe are called directives. thing:something syntax added to the HTML. Remember when I said there's no such thing as plain HTML in modern JS? 😛

    We used the on: directive to make buttons work

    <button on:click="{prevMovie}" style="grid-area:b1">👈</button>
    

    Call the prevMovie function when the button is clicked.

    That's it. No binding. No passing params. No nothing. Svelte figures it all out on its own.

    Svelte's template logic

    This is where I think Svelte fumbles. Svelte's template logic is easy to use, but reminiscent of old Mustache or Handlebars syntax.

    {#if user.loggedIn}
            <button on:click={toggle}>
                Log out
            </button>
        {:else}
            <button on:click={toggle}>
                Log in
            </button>
        {/if}
    

    Not sure how I feel about that 🤔

    Easy to read, yes, easier to write than React's nested ternary expressions, definitely, but means you have to learn another syntax beyond JavaScript, CSS, and HTML. Which can be good or bad.

    Depends what you're doing I guess. For simple stuff this is great.

    The verdict?

    Svelte is great. Quick to get started, easy to use, good ergonomics, not too complex. Like other frameworks, I'd have to build some bigger projects to see how it feels in the real world.

    That's where I've found in the past that React shines. With bigger more complex projects. Whereas Vue, in my experience, is quick to get started but breaks down with complexity.

    Svelte? I don't know yet.

    But it feels like Svelte takes the best of React and the best of Vue to make something awesome.

    I recommend you dig through the examples. They're great and show off Svelte's best features.

    Like the built-in transition support. Love it 👌

    Published on May 20th, 2019 in Front End, Technical

    Did you enjoy this article?

    Continue reading about Svelte takes the best of React and the best of Vue to make something awesome

    Semantically similar articles hand-picked by GPT-4

    Senior Mindset Book

    Get promoted, earn a bigger salary, work for top companies

    Learn more

    Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.

    Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.

    Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.

    Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev

    Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization

    Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections

    Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog

    Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

    By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️

    Created by Swizec with ❤️