My experience with Svelte
Posted on Sunday, 27 September 2020
8 minutes to read
Introduction
Phew lads, I finally tried using Svelte and boi oh boi was it an awesome experience. I've been holding my self to try svelte because the editor that I'm using which is Neovim doesn't support svelte really well back then. I decided to try it again this time and it works great now.
Why Svelte?
If you don't know, I usually use React for building a website. I love React and its concept but I want to try something else that is different. Why not Vue? you might ask. Well, to be honest it's hard for me to wrap around my head on how Vue works. It's also because Svelte is quite a new library and it is unique. It doesn't use Virtual DOM like most of SPA framework does.
To be fair, Svelte is actually a language that compiles to pure javascript that we all know and hate love. There are other languages that also tries to desribe interactive user interface such as Imba, Elm, Marko and many more.
My Experience
Almost feel like a vanilla
My first impression was like, man, this is just like a vanilla html with some sugar on top of it. It looks similar to Vue syntax but more flexible so to speak. Vue's html has to be placed inside of <template/>
tag whereas Svelte isn't. You can place it literally anywhere. Take a look at this.
<style>
.heading {
color: aqua;
}
</style>
<Navbar title="An epic title">
<h1 class="heading">{heading}<h1>
<div>
<p>{paragraph}</p>
</div>
<Footer />
<script>
import Footer from "./_components/Footer.svelte"
let heading = "This is a heading"
let paragraph = "This is a heading"
</script>
It looks very similar to pure html isn't it? I also prefer Svelte syntax over Vue syntax because it looks more similar to React. What I mean by that is, if you want to run a javascipt expression, they both uses {}
. For example.
<!-- React -->
<Counter count={count}/>
<!-- Svelte -->
<Counter count={count}/>
<!-- or shorthand if you prefer -->
<Counter {count}/>
<!-- Vue -->
<Counter v-bind:count={count}/>
What I've made using Svelte
I've made 2 websites using Svelte. The first one is Three Of Something which is a place where I put the result of small challenge where I implement a UI design that I found to code. I do this challenge every week with both of my friends, NikarashiHatsu and LynSotera. Here's a screenshot of the homepage.
Go visit the website if you're interested ツ
The second website that I made is Kanaizu. It's basically some sort of quiz app where you need to type the correct romaji for the shown kana. The main reason of why I made this app is because I want to learn more about Svelte and to help my friend memorise Japanese kana. Here's the homepage of it.
Again, go visit the website if you're interested ツ
To be fair, I made those using Routify. Basically, Routify handles the routing. I didn't use Sapper because it's too much for what I need. I just need a basic routing and Routify is perfect.
What I've learned so far
After making those 2 sites, I ofcourse learned something new and I'm so happy that I finally decided to try Svelte.
Components
On React, a component is a function that returns a JSX. It looks something like this.
export default () => <p>Hello World!</p>
On Svelte, the whole file is a component. It uses .svelte
extension and the syntax is basically a superset of HTML. It looks something like this.
<style>
/* some stylings */
</style>
<!-- some epic html stuff -->
<script>
// some logic goes here
</script>
The order doesn't really matter but I prefer style-markup-script
because I like the markup to be in the middle of the stylings and the script.
Props
Apparently, props in svelte is just an exported let
variable. So what you would do to make a prop is something like this.
Counter.svelte
<div>
{count}
</div>
<script>
export let count
</script>
App.svelte
<div>
<Counter count="{1}"/>
</div>
<script>
import Counter from "./counter.svelte"
</script>
Scoped stylings
Styling in Svelte is scoped! Because you write the styling on the same file as the rest of the component, it became scoped. You can still change the global styling using :global()
though.
Global state
Next thing that I learned is global state or store. Usually in React, I need React.Context
to store a global state. On Svelte, I need to use svelte/store
. Global state is much simpler in Svelte in my opinion. Here's a comparison between them.
context.js
import React, { createContext, useState } from "react"
export const CountContext = createContext(null)
export const CountProvider = ({ children }) => {
const [count, setCount] = useState(0)
return (
<CountContext.Provider value={{ count, setCount }}>
{children}
</CountContext.Provider>
)
}
app.js
import React, { useContext } from "react"
import { CountProvider, CountContext } from "./context"
export default () => {
const { count, setCount } = useContext(CountContext)
return (
<CountProvider>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
</CountProvider>
)
}
Well, it looks like a lot but it's actually quite simple if you know how React Context works. Now let's compare it with Svelte.
stores.js
import { writable } from "svelte/store"
export const count = writable(0)
app.svelte
<p>{$count}</p>
<button on:click={count.update(n => n + 1)}>Increment</button>
<button on:click={count.update(n => n - 1)}>Decrement</button>
<script>
import { count } from "./stores"
</script>
I mean, just look at how simple it is. Bare in mind that this post isn't meant to explain every single thing that Svelte has to offer so please refer to the official website for more explanation ツ
Actually, Svelte also has Context API. Since I'm still learning, please read this article for better understanding. It's such a good article and you should definitely check it out!
Animation and transition directive
Svelte provides animation and transition that you can use to animate your components. The usage is also simple, what you would do is just something like this.
Transition.svelte
<button on:click={isVisible = !isVisible}>Toggle</button>
{#if isVisible}
<p transition:fade>This text is visible</p>
{/if}
<script>
import { fade } from "svelte/transition"
let isVisible = false
</script>
The transition directive is triggered whenever an element leaves or enter the DOM tree. More details about transition directive is available here.
I used transition for Kanaizu but I haven't tried the animate directive since I haven't found the use case for it.
Logic blocks
Last one is logic blocks. On React, you can use curly braces {}
to write some Javascript logics and return something that will get rendered. Here's an example.
import React, { useState } from "react"
export default function Counter() {
const [isVisible, setVisible] = false
return (
<div>
{isVisible && <div>I'm Visible!</div>}
<button onClick={() => setVisible(!isVisible)}>Toggle</button>
</div>
)
}
It's a little bit different on Svelte. It looks something like this.
{#if isVisible}
<p>I'm Visible!</p>
{/f}
<button on:clock={isVisible = !isVisible}>Toggle</button>
<script>
let isVisible = false
</script>
I like them both so it doesn't really matter. There's also quite a few on Svelte's docs.
Conclusion
Well, I fell in love with this language. It's so simple yet it's so good. Sorry if the highlighting looks weird in this post because I couldn't make it work for Svelte or JSX syntax :p
I want to rebuild this blog using Sapper + MDSveX in the future. Don't get me wrong, Gatsby is great. I just want to try out something new. Svelte's bundle size is also smaller compared to React, that's also why ツ
Thanks for reading this! You should definitely try Svelte, you wouldn't regret it. Anyway, have a good day folks! =)
javascript