1. 關注度持續上升
根據 State of JS 的調查,Svelte 在 2019 年納入問卷選項,當時的滿意度就有 88%(React 89%, Vue 87%),今年變成 89% 變成滿意度第一名的前端框架。
另外原本使用率在 2019 年為 8% 排名為第六,在 2020 年變為 15% 晉升為第四名。代表越來越多人在關注這個前端框架了。
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 變數等,可能反而造成混肴。
Svelte 需要事先編譯的特性也代表著它無法像 Vue 一樣直接在
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 有興趣,不妨參考一下過去我寫的文章