半熟前端

軟體工程師 / 台灣人 / 在前端的路上一邊探索其他領域的可能性

前端

2021 年值得學習 Svelte 的四個理由

2021 年值得學習 Svelte 的四個理由

1. 關注度持續上升

根據 State of JS 的調查,Svelte 在 2019 年納入問卷選項,當時的滿意度就有 88%(React 89%, Vue 87%),今年變成 89% 變成滿意度第一名的前端框架。

Screenshot_2021-02-09 State of JS 2020 Front-end Frameworks

另外原本使用率在 2019 年為 8% 排名為第六,在 2020 年變為 15% 晉升為第四名。代表越來越多人在關注這個前端框架了。

Screenshot_2021-02-09 State of JS 2020 Front-end Frameworks(1)

2. 入門門檻低,容易上手

Svelte 的語法幾乎與 HTML 完全相容,另外像是 {#if} {#each} 等模板語法如果有寫過像是 .ejs .pug 的話也非常容易理解。Svelte 語法設計目的在於減少心智負擔,所以初學者只要掌握基本觀念之後也可以很快上手。一個 svelte 元件看起來像這樣子

<script>
  export let prop; // prop 這樣宣告
  let count = 1; // 變數這樣宣告
  onMount(() => { // 生命週期方法
    count++; // 改變變數值會觸發元件更新
  })
</script>

<style>
  p { font-size: 14px }
</style>

<!-- 變數用 {} 包起來 -->
<p>{count}</p> 

<!-- 屬性傳遞 -->
<Component count={count} />

不需要額外學習 hooks 的概念也可以輕鬆看懂元件的樣貌,styling 的部分因為 Svelte 會在編譯時加入 hash 所以也不需要擔心 css 命名衝突。這些全部都在 Svelte 的實作當中,代表不需要額外的 loader (css-module) 來處理。

對於那些原本以後端開發為主,臨時需要前端頁面開發時,Svelte 就是一個非常容易上手且能快速投入開發的好工具。

3. Bundle size 體積小

比起 React 或 Vue,Svelte 會先編譯後再生成程式碼,所以可以做到一些編譯優化或是在編譯時做到依賴追蹤的機制。有興趣的讀者可以參考作者本人寫的「Virual DOM is pure overhead」,裡頭就有提到為了避免直接操作 DOM API 達成宣告式的效果,勢必會需要拿一些效能來換,以 React 舉例就是 Virtual DOM 與 diff 機制。為了讓 diff 的成本足夠小且可以相容多平台,React 需要更輕量的機制來描述 render tree,也就是 Virtual DOM。

在大型應用當中如果遇到效能問題,為了讓開發者有自己調整效能的空間,React 提供了各種優化機制如 useMemo shouldComponentUpdate 等 API 給開發者操作。

Svelte 也沒有 Virtual DOM 的概念,最重要的依賴追蹤機制也在靜態時期分析好了,所以 runtime 的 bundle size 會比 React 與 Vue 小很多,也就意味著在中小型應用當中 Svelte 往往具有更小的 bundle size、更好的效能。

4. 內建 transition, animation 機制

Svelte 有內建 transition 功能,和開發中常見的場景整合非常好,甚至在 Svelte 當中還有內建常見的 transition 機制,你可以用 transition 這個 directive 來達到過渡效果,Svelte 會幫你判斷何時該執行過渡效果(進、出場)。

在 Svelte 當中你可以這樣寫:

<script>
  import { scale } from "svelte/transition";
  import { onMount } from "svelte";

  let toggle = false;

  onMount(() => {
    setInterval(() => {
      toggle = !toggle;
    }, 2000);
  });
</script>

<main>
  {#if toggle}
    <h1 transition:scale>Hello World</h1>
  {/if}
</main>

{#if toggle} 為 true 時 h1 會渲染(進場),false 的時候則會移除(出場)。加入 transition:scale 之後,Svelte 會在適當的時機點執行 transition。

以 React 來說通常要使用 react-transition-group,不然直接寫成 toggle && <Component /> 會在 toggle 為 false 時直接 unmount 元件,而無法順利執行 transition,或是使用 react-spring 來做到更進階的動畫互動。

看到這裡 Vue 開發者可能會覺得這有什麼好稀奇的,vue 也是內建 transition 機制,在 v-if 判斷下也會執行對應的 transition。不過差別在於 vue 必須自行定義 classname 與 transition 的實作在 css 當中,但是 Svelte 可以透過宣告式的方式進行,而不用另外在 css 定義 classname。

「反正一定是直接用 JavaScript 修改 inline style 這種效能爛到爆的方式啦」

事實上 Svelte 會動態產生 css keyframe,生成動畫的原始碼在這裡:

function go() {
  const {
    delay = 0,
    duration = 300,
    easing = linear,
    tick = noop,
    css
  } = config || null_transition;

  if (css) animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++);
  ...
}

這邊的 create_rule 是整個 transition 機制的核心,背後的實作是透過 stylesheet.insertRule 完成,假設我宣告了一個 transition

function myTransition(node) {
  return {
    css: t => `
      transform: scale(${1 - t});
    `;
  }
}

實際會上產生一個 animation keyframe(透過 insertRule):

@keyframes svelte_hash_animation_name {
  0% {
    transform: scale(0);
  }
  
  10% {
    transform: scale(0.1);
  }
  
  20% {
    transform: scale(0.2);
  }
  
  30% {
    transform: scale(0.3);
  }
  ...
}

然後加入到要執行動畫的 DOM 節點當中。進而避免每一個 frame 都要修改 inline style 耗費不必要的效能。

crossfade 與 FLIP 效果容易實作

直接用範例會比較快理解,請點擊頁面中的按鈕看看實際效果:

在點擊時,標籤會從現在位置到目的位置進行 transition,最後停在最終位置,這個效果可以輕鬆用 svelte 完成,另外在點擊標籤時還會發現其他的標籤位置跟著做 transition 了,這樣子可以讓互動看起來更順暢。這個稱為 FLIP 的技巧在 Svelte 當中也有實作。

缺點

講完以上優點,接下來要來結合自己的經驗講講使用上的缺點了。

1. 編譯時期做太多事

比如說 Svelte 在靜態時期會幫你做依賴追蹤,或是生成的程式碼有時想要自己 debug 看看是否有奇怪的地方要調整,這個時候就會變得比較難 debug。

另外對於熟悉 HTML 的開發者來說可能沒什麼,但對於新手來說 Svelte 元件和 HTML 很像但又有不同之處,例如 {} 語法跟 reactive 變數等,可能反而造成混肴。

2. 必須符合 Svelte 定義的元件格式

為了建立 Svelte 元件,你必須按照 Svelte 的元件格式撰寫。像是 React 當中,所有的元件都是 JavaScript 檔,所以只要是合法的 JavaScript 都可以撰寫 React 元件。

3. 相對其他前端框架資源較少、生態系尚未完善

雖然最近 Svelte 資源不斷增加,但仍然以英文為大宗,中文的資源仍然相對較少。所以有問題時也會比較難找到解答,,解決方案也不像其他前端框架那麼完善,這點只能靠時間來解決了,或是一起動手創造更多 Svelte 相關資源!

4. 使用率仍然偏低

對於大部分公司而言,Svelte 使用率仍然偏低,對於求職來說或許不是最佳選擇。

總結

Svelte 跟其他前端框架有了明顯不同的定位,簡潔的語法、編譯思想、write less code、small bundle size 等優勢讓 Svelte 在近幾年逐漸獲得重視。我自己很喜歡這樣的多樣性,儘管不一定每個人都會喜歡,但是有思想上的衝撞才能帶來更多進步空間甚至是靈感啟發。在 2021 年即將進入新年的時期,不妨暫且擱下自己熟悉的前端框架,試試看這門 2020 年滿意度第一的 Svelte 吧!

如果你對 Svelte 有興趣,不妨參考一下過去我寫的文章