點燈坊

失くすものさえない今が強くなるチャンスよ

Svelte 初體驗

Sam Xiao's Avatar 2019-11-23

Svelte 是 2019 年最受注目的新前端 Framework,其 Compiler 技術有別於 Virtual DOM,不僅 Bundle Size 超小,執行效率直逼 Vanilla JS,且 Codebase 非常精簡,其 Class-free 風格特別適合 FP。

Version

macOS Catalina 10.15.1
WebStorm 2019.2.4
Node 13.1.0
Svelte 3.0.0

Create Project

$ npx degit sveltejs/template svelte-counter

使用 degit 根據 sveltejs/template 建立 svelte-counter project。

overview000

$ cd svelte-counter
$ yarn

使用 Yarn 安裝其 dependency。

overview001

$ yarn dev

Svelte 已內建 dev server,可使用 yarn dev 啟動。

overview002

overview003

Svelte 的 Hello World 已經可在本機成功執行。

VS Code

overview005

VS Code 可安裝 Svelte 支援 Svelte。

WebStorm

overview010

WebStorm 也可安裝 Svelte 支援 Svelte。

Project Architecture

overview004

  • publicyarn build 之後檔案,適合 deployment 使用
  • src:Svelte 的 codebase,main.js 為啟動檔,App.svelte 為 component
  • package.json:注意 svelte 是放在 devDepencies,因為 Svelte 本質是 compiler,負責將 codebase 在 build-time 產生 Vanilla JS,因此放在 devDepencies 即可,這也是 Svelte 的 bundle size 會超小原因

src/main.js

import App from './App.svelte';

const app = new App({
  target: document.body,
  props: {
    name: 'world'
  }
});

export default app;

main.js 為 Svelte 的進入點,以 App.svelte 建立 App root component,並傳入 worldname property。

src/App.svelte

<script>
  export let name;
</script>

<main>
  <h1>Hello {name}!</h1>
  <p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
</main>

<style>
  main {
    text-align: center;
    padding: 1em;
    max-width: 240px;
    margin: 0 auto;
  }

  h1 {
    color: #ff3e00;
    text-transform: uppercase;
    font-size: 4em;
    font-weight: 100;
  }

  @media (min-width: 640px) {
    main {
      max-width: none;
    }
  }
</style>

Svelte 的 component 的 extension 為 .svelte

Svelte 的 .svelte 很類似 Vue 的 .vue,將 HTML、CSS 與 JavaScript 寫在同一個檔案,JavaScript 寫在 <script> 內,CSS 則寫在 <style> 裡,HTML 不必如 Vue 寫在 <template> 內。

第 1 行

<script>
  export let name;
</script>

<main>
  <h1>Hello {name}!</h1>
  <p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
</main>

Svelte 習慣將 <script> 寫在最上方,若你想類似 Vue 將 HTML 寫在最上方也行。

nameApp component 的 props,只需簡單使用 ES6+ 的 export 即可,且 HTML 也可立即取得 prop 做 binding。

我們可發現 component 內沒有 class 也沒有 function,甚至連 instance 也沒有,非常簡潔

My Counter

src/App.svelte

<script>
let count = 0
$: squared = count ** 2

let onClick = () => count += 1

</script>

<p>{ count }</p>
<p>{ squared }</p>
<button on:click={ onClick }>+</button>

另外一個檢驗 framework 常用指標就是觀察如何實踐 counter,因為這牽涉到 state、data binding、event binding 與 reactive 如何處理。

第 2 行

let count = 0

<p>{ count }</p>

Svelte 在 JavaScript 的 variable 都可拿來做 data binding,不像 React Hooks 必須使用 state hook,也不必如 Vue 必須宣告在 data property 下。

第 5 行

let onClick = () => count += 1

<button on:click={ onClick }>+</button>

Svelte 在 JavaScript 的 function 都可拿來做 event binding,這在 React Hooks 也可行,但 Vue 必須宣告在 methods property 下的 function 才可。

另外一個重點是 onClick() 可直接存取 count state,這在 React Hooks 也可行,但 Vue 必須使用 this.count 才能存取,也由於這個 this,導致 Vue 在重構時非常困難,且不利於與 Ramda 等 FP library 搭配;但 Svelte 完全不需 this 即可處理 state,易於重構與 FP 使用。

第 3 行

$: squared = count ** 2

<button on:click={ onClick }>+</button>

若要如 Vue 有 computed 也不是問題,只要加上 $ label 代表 stream,則 squared 會根據 count 改變而自動 reactive 改變。

overview006

Bundle Size

$ yarn build

Bundle size 也是檢驗 framework 重要指標之一,Svelte 經過 yarn build 之後只有 2K。

overview009

Svelte 的 bundle size 之所以這麼小,是因為他與 React、Vue 走了完全不同技術。

React、Vue 背後使用 Virtual DOM 需要 runtime,因此 bundle size 必須包含基礎 runtime 部分。

Svelte 則透過 compiler 直接編譯成 Vanilla JS 操作 DOM,也因為沒有 runtime,因此 bundle size 超小。

Performance

overview007

Svelte 因為不透過 Virtual DOM,因此速度直逼 Vanilla JS。

Conclusion

  • Svelte 算我使用過最精簡的前端 framework,且完全不使用 this,非常適合 FP 風格
  • Svelte 官網寫的很棒,透過官網可快速入門,也提供 REPL 線上直接測試
  • Svelte ecosytem 則值得關注,很可能成為 VAR 之外新選擇

Reference

Svelte, Tutorial