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>

Sum up

Next steps

A hitchhiker's guide to Svelte JS

By Farzad Yousefzadeh

A hitchhiker's guide to Svelte JS

It's been a while since SvelteJS was introduced as yet another Javascript solution to build fast and robust web applications. in this talk, we'll dive into what svelte is and try to fashion a high level understanding of its building blocks. if you don't know Svelte yet or you've heard of it but haven't had the chance to get to know it yet, fear not, I'm like you. let's do it together.

  • 1,785