2022年にSvelteを学ぶべき4つの理由
1. 注目度の上昇が続いている
State of JS の調査によると、Svelteは2019年にアンケートの選択肢に追加され、当時の満足度はすでに88%(React 89%、Vue 87%)に達していた。そして今年には89%となり、満足度第1位のフロントエンドフレームワークとなった。

また、使用率は2019年の8%(第6位)から、2020年には15%(第4位)へと浮上した。これは、より多くの人々がこのフロントエンドフレームワークに注目し始めていることを示している。

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の概念を別途学ぶ必要がなく、コンポーネントの構造を直感的に把握できる。スタイリングに関しても、Svelteがコンパイル時にハッシュを付与してくれるため、CSSの命名衝突を心配する必要もない。これらはすべてSvelte自身に組み込まれており、追加のローダー(CSS Modulesなど)で処理する必要がないことを意味している。
普段はバックエンド開発がメインで、急遽フロントエンドの画面開発が必要になったような開発者にとって、Svelteは非常に扱いやすく、素早く開発に着手できる優れたツールだ。
3. バンドルサイズが小さい
ReactやVueと比べると、Svelteは事前にコンパイルを行ってからコードを生成するため、コンパイル時の最適化や依存関係の追跡メカニズムを実現できる。興味のある読者は作者自身が書いた「Virual DOM is pure overhead」を参照してほしい。そこでは、DOM APIを直接操作するのを避けて宣言的なUIを実現するためには、ある程度のパフォーマンスを犠牲にする必要があると言及されている。Reactを例にとると、仮想DOM(Virtual DOM)とdiffのメカニズムがそれに該当する。diffのコストを十分に抑え、マルチプラットフォームに対応させるために、Reactはレンダーツリーを表現するより軽量な仕組み、すなわち仮想DOMを必要とする。
大規模アプリケーションでパフォーマンス問題に直面した場合、開発者がパフォーマンスを独自に調整できるように、Reactは useMemo や shouldComponentUpdate などの各種最適化APIを提供している。
一方で、Svelteには仮想DOMの概念がなく、最も重要な依存関係追跡メカニズムも静的解析の段階で完了している。そのため、ランタイムのバンドルサイズはReactやVueよりもはるかに小さくなり、中・小規模のアプリケーションにおいては、Svelteは往々にしてより小さなバンドルサイズと優れたパフォーマンスを発揮する。
4. トランジションやアニメーションの仕組みが組み込まれている
Svelteにはトランジション機能が組み込まれており、開発でよくあるユースケースと非常によく統合されている。それどころか、Svelteには一般的なトランジション機構があらかじめ用意されており、transition ディレクティブを使うだけでトランジション効果を実現できる。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が適切なタイミングでトランジションを実行してくれる。
Reactの場合、通常は react-transition-group を使う必要がある。さもなければ toggle && <Component /> と書いただけでは、toggleが false になった瞬間にコンポーネントがアンマウントされてしまい、トランジションが正常に実行されない。あるいは、より高度なインタラクションを実現するために react-spring などを導入することになる。
ここまで読んで、Vueの開発者は「そんなの珍しくもない、Vueにもトランジション機能は内蔵されているし、v-if の判定で対応するトランジションが走る」と思うかもしれない。しかし違いは、VueではCSS側でクラス名やトランジションの実装を自分で定義しなければならない点にある。それに対してSvelteは、CSSでクラス名を別途定義することなく、宣言的に記述できるのだ。
「どうせJavaScriptでインラインスタイルを直接書き換えるような、パフォーマンス最悪のやり方なんだろう」
実際には、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 がトランジションメカニズム全体の中核であり、その内部実装は stylesheet.insertRule によって行われている。仮に僕が以下のようなトランジションを宣言したとする:
function myTransition(node) {
return {
css: t => `
transform: scale(${1 - t});
`;
}
}
実際には(insertRuleを介して)以下のようなアニメーションのkeyframeが生成される:
@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ノードに追加される。これにより、毎フレームごとにインラインスタイルを書き換えるような無駄なパフォーマンス消費を回避している。
crossfadeとFLIPエフェクトが簡単に実装できる
例を見たほうが理解が早いだろう。ページ内のボタンをクリックして実際のエフェクトを確かめてみてほしい:
クリックすると、タグが現在位置から目的の位置へとトランジションし、最終的な位置に収まる。このエフェクトはSvelteを使えば簡単に実現できる。また、タグをクリックした際、他のタグの位置も連動してトランジションしているのが分かるはずだ。これによりインタラクションが格段に滑らかに見える。このFLIPと呼ばれるテクニックも、Svelteには標準で実装されている。
デメリット
ここまでメリットを挙げてきたが、次は僕自身の経験も交えて、使ってみて感じたデメリットについても語っていきたい。
1. コンパイル時に多くのことをやりすぎている
例えば、Svelteは静的解析の段階で依存関係の追跡を行ってくれるが、生成されたコードにおかしな点がないか自分でデバッグして調整したいときに、デバッグが難しくなることがある。
また、HTMLに慣れている開発者にとっては大した問題ではないかもしれないが、初心者にとってはSvelteコンポーネントがHTMLに酷似していながら異なる部分({} 構文やリアクティブな変数など)があるため、かえって混乱を招く可能性がある。
Svelteの「事前コンパイルが必要」という特性は、Vueのように <script> タグでライブラリを直接読み込んで即座に使うということができず、ViteやWebpackといったビルドツールを経由しなければ実行できないことも意味している。
2. Svelteが定義するコンポーネント形式に従う必要がある
Svelteコンポーネントを作成するには、Svelte独自のコンポーネント形式に沿って記述する必要がある。例えばReactではすべてのコンポーネントが JavaScript ファイルであるため、正当な JavaScript であればどのような書き方でもReactコンポーネントを作成できる。
3. 他のフロントエンドフレームワークに比べてリソースが少なく、エコシステムが未成熟
最近でこそSvelteのリソースは増え続けているものの、依然として英語が中心であり、中国語のリソースはまだ比較的少ない。そのため問題に直面したときに答えを見つけにくく、ソリューションも他のフロントエンドフレームワークほど充実していない。この点は時間に頼るしかないし、あるいは僕たち自身で手を動かしてSvelte関連のリソースをもっと作り出していくしかない。
4. 使用率が依然として低い
多くの企業においてSvelteの採用率はまだ低く、就職・転職活動という観点ではベストな選択肢とは言えないかもしれない。
まとめ
Svelteは他のフロントエンドフレームワークとは一線を画す明確なポジションを築いている。簡潔な構文、コンパイル重視の思想、write less code、small bundle sizeといった強みによって、Svelteはここ数年で着実に注目を集めてきた。僕自身、こうした多様性がとても好きだ。誰もが気に入るわけではないかもしれないが、思想のぶつかり合いがあってこそ、さらなる進化の余地やインスピレーションが生まれるのだと思う。2021年も年の瀬を迎え新たな年に入ろうとしている今、普段使い慣れているフロントエンドフレームワークを一旦脇に置いて、2020年に満足度第1位に輝いたSvelteを試してみてはどうだろうか。
もしSvelteに興味が湧いたなら、過去に僕が書いた記事もぜひ参考にしてみてほしい。
関連記事
- Three.js で僕の部屋を表現する 僕が React Three Fiber を使って実際の自分の部屋をブラウザ上に再現し、実世界のオブジェクトを目録に見立て、空間の記憶を通してここ数年の生活と仕事について語った話。
- フロントエンドで画像を扱う際に注意すべきこと Jake Archibaldの記事を起点に、現代のレスポンシブ画像の書き方を整理する。なぜwidth/heightを付ける必要があるのか、CSSのaspect-ratioはいつ使うべきか、AVIFとWebPの選び方、そしてpicture/source/srcsetを使ったモバイル向け画像の切り替えについて。
- CSS field-sizing — たった1行のCSSでフォーム要素を自動リサイズする かつてtextareaの自動高さ調整は、JavaScriptでscrollHeightを監視するしかなかった。しかしCSSのfield-sizing: contentなら、わずか1行で代替でき、textarea、input、selectに対応している。本記事では従来のやり方のペインポイントと、field-sizingの使い方をまとめる。
- リンクの下線をもっと見栄え良くする:text-underline-offset デフォルトでは下線と文字が近すぎて、このスタイルを好まないデザイナーもいるし、僕自身もあまり綺麗ではないと感じていた。