A hitchhiker's guide to svelte.js
Farzad Yousefzadeh

HelsinkiJS Dec 2019

Farzad YousefZadeh
Formerly:
Aerospace engineer 🚀 astrophysicist 🌌
farzadyz.com
Svelte is a compiler
*.svelte
Almost no Runtime
Bare minimum a11y



DEAD code elimination
{
c() {
h1 = element("h1");
t0 = text("Hello ");
t1 = text(name);
t4 = space();
img = element("img");
},
m(target, anchor) {
insert(target, h1, anchor);
append(h1, t0);
append(h1, t1);
insert(target, t4, anchor);
insert(target, img, anchor);
}
};
Compiler output is readable!
Svelte is also a FRAmework
View: HTML template
logic: Javasript
Style: scoped + global css
App.svelte
// only 1 script
<script>
</script>
// only 1 style
<style>
</style>
// the rest is view
<p>Text</p>
<Test />
Every *.svelte file is a component
Module system
elements starting with lowercases
// App.svelte
<script>
import Button from './Button.svelte'
</script>
<h1>Some title</h1>
<Button>Click me</Button>
Components starting with uppercases
component is default export of file
HTML template
<h1>HTML Tags</h1>
<a href="/pages/{nextPage}">Next</a>
<a href={nextPageURL}>Next</a>
<CustomComponent {...props} />
<p>Page is {currentPage}</p>
{#if expression}...{/if}
{#if expression}...{:else if expression}...{/if}
{#if expression}...{:else}...{/if}
{#each expression as name}...{:else}...{/each}
Suspending view
{#await promise}
<!-- promise is pending -->
<p>waiting for the promise to resolve...</p>
{:then value}
<!-- promise was fulfilled -->
<p>The value is {value}</p>
{:catch error}
<!-- promise was rejected -->
<p>Something went wrong: {error.message}</p>
{/await}
scoped & global styles
p {
color: tomato; // p.svelte-1fj21zt{ color:tomato }
}
:global(.text) {
color: teal; // .text{ color:teal }
}
:global(div > strong) {
color: blue; // div > strong{ color:blue }
}
:global(body) {
margin: 0; // body{ margin:0 }
}
div :global(strong) {
color: goldenrod; // div.svelte-1fj21zt strong{ color:goldenrod }
}
props and state
<script>
// props
export searchQuery = ""
export initialPageItems = []
// state
let fetchState = "pending"
let allItems = [].concat(initialPageItems);
// Normal variable
const PER_PAGE = 10
</script>
lifecycle methods
<script>
import {onMount, onDestroy, beforeUpdate, afterUpdate} from "svelte"
onMount(() => {
// code
return () => {
// cleanup
}
})
onDestroy(() => {
// cleanup
})
</script>
svelte is reactive
Reactivity with assignment
reactive statements
parent-child communication
parent-child communication
parent-child communication
Distributed stores (writable stores)
import {writable} from "svelte/store"
export const userStore = writable({username: '', repos: []})
/*
const unsub = userStore.subscribe(value => {
// do something with updated value
})
userStore.update(currentState => newState)
userStore.set(newState)
*/
Auto-subscribe (writable stores)
<script>
import {timerStore} from './timerStore.js'
let timer
let id
id = timerStore.subscribe(newTime => {
timer = newTime
})
onDestory(() => {
clearInterval(id)
})
</script>
<p>Timer: {timer}</p>
<script>
import {timerStore} from './timerStore.js'
</script>
<p>Timer: {$timerStore.value}</p>
Distributed stores (readable stores)
import {readable} from "svelte/store"
export const userStore = readable(defaultValue, (setState) => {
setState(...)
return () => {
// unsubscribe
}
})
Derived stores
import {readable} from "svelte/store"
export const userStore = readable(defaultValue, (setState) => {
setState(...)
return () => {
// unsubscribe
}
})
const start = new Date();
export const elapsed = derived(
time,
$time => Math.round(($time - start) / 1000)
);
Special elements
// recurive components
<svelte.self />
// bind to window events
// attach event handlers
<svelte.window />
// Same as Helmet in React
<svelte.head />
// attach to body events
// bind to body values
<svelte.body />
Dynamic children
// Button.svelte
<button>
<slot></slot>
<slot>
<strong>Fallback of no children</strong>
</slot>
</button>
compound components
// Button.svelte
<button>
<slot name="icon"></slot>
<slot name="text"></slot>
</button>
// App.svelte
<Button>
<slot name="icon">
<svg />
</slot>
<slot name="text">
<em>Italic button text</em>
</slot>
</Button>