Zenn
🐒

Sveltekitを使用したSNS作ってみた 感じたSvelteのメリットとデメリット

2025/02/24に公開

この度Sveltekitを使用して、2(MhYg)という自分史(自分の歴史みたいなもの…)を共有できるSNSを作ってみました。
https://2mhyg.kyouryoku.net
これまで自分はNext.js以外でまともなアプリケーションを実装したことがなかったのですが、今回はSveltekitを採用しました。
採用した理由は、気分…の部分が大きいですが、もうちょっとまともな理由として以下のようなものが挙げられます。

  • 既存のReactで書いたプロジェクトが肥大化してコードが分かりづらくなっている。svelteの簡潔な文法ならもっと分かりやすく書けるのではないか。
  • React以外のフレームワークに触れてみたい

ただ、開発を終えて一つ間違いなく言えることは、「Svelteは良い!」ということです。
デメリットも多くあるのですが、個人的にはメリットの方が大きかったです。
ということで、この記事ではSvelteのメリットとデメリットをいくつか紹介しようと思います。

0. Svelteについてざっくり紹介

公式サイトによると、Svelteはコンパイラを使用したUIフレームワークです。ReactやVue.jsのようなものという認識で構いません。特に大きい特徴は、簡潔な文法でコンポーネントを記述できること、仮想DOMを使用しないこと、コンパイルによりクライアントでの実行が最小限に抑えられることです。.svelteというファイルを作成することで、コンポーネントを記述することができ、これをコンパイルすることでブラウザ上で実行できる状態になります。2022年からはSveltekitの登場によってサーバーサイドでの実行もサポートされるようになり、今注目されているJavaScriptライブラリの一つです。
https://svelte.jp

1. デメリット

デメリットを聞きたい人の方が多いと思うので、デメリットから書かせてもらいます。

1. 情報が少ない

どんなライブラリ、フレームワークでもマイナーなものは絶対にこの問題に直面します。
Svelte、SveltekitはReactやNext.jsよりも調べた時に出てくる情報が圧倒的に少ないです。
また、情報が出てきたとしても英語であることが多いです。英語が得意な人であればそこまで問題にならないかもしれませんが、私のような英語が苦手な人の場合、deepL等翻訳アプリを駆使する必要があるため、大変面倒です。
それでも、公式ドキュメントが充実していればなんとかなることが多いですが、たまに公式ドキュメントにも載っていない機能に出会うことがあります。(例:mountunmount関数など。私の調べ不足かもしれませんが)
また、最近はChatGPTやGemini、Claudeなど生成AIの力を借りる方も多いと思いますが、Reactのコードを書かせたときよりも間違ったコードを書く頻度が高いです。
このように情報が少ないという点が、Svelteを使う上で一番のデメリットです。Svelteのエコシステムがもっと成熟すればこの問題は自然解決していくと考えられますが、果たしてそのような時は来るのでしょうか?今後に期待ですね。

2. Svelte5とそれ以前で全く書き方が違う

2025年2月現在、Svelte5がSvelteの最新バージョンです。このSvelte5では新しい書き方が導入されました。
runeと呼ばれるこの書き方はこれまでと根本から異なるため、以前の書き方とは互換性がありません。
そのため、runeを使わない書き方をされている記事などは参考程度にしかなりません。また多くの生成AIも以前の書き方をしてくることがよくあります。一応「runeを使用して」のように制限をかければある程度は解決しますが、それでもニッチな実装を行う場合など、互換性のない書き方をされることがあります。
この事が、1で述べた情報が少ないという問題点に拍車をかけているように感じます。
ただ、rune自体はとても良い機能です。ここで、runeの何が良いか書きたいところですが、あくまでもデメリットを書かないといけないので、後々書かせていただこうと思います。

3. 副作用が実行されるタイミングを制御しにくい

ReactではuseEffectを使用することにより、ステートが変更された後に特定のコードを実行することができます。このuseEffectを実行するタイミングは、第二引数に依存配列を渡すことで制御することができます。
svelte5のruneの場合、$effectを使用することで似たようなことができます。
この、$effectの仕組みとしては副作用として実行される関数のコードを読み解いて依存関係にある変数が変更されたときのみ実行されるようです。
しかし、$effectではuseEffectのようにどのステートが変更されたらこのコードを実行するか指定することができないため、意図しないタイミングで副作用が実行されることがあります。
一応解決策として、untrack関数で囲むことで、内部の変数を依存関係として認識しないようにする、もしくは、$derivedなどを活用することが考えられます。
Svelteを使い始めたばかりの頃は不便に感じていましたが、最近は変な実装はするなよというSvelteからのメッセージだと捉えています。

4. 記事のコードがハイライトされていない

svelteでは.svelteという独自の拡張子を使用したファイルで記述します。そのため、svelteについて調べた際出てくる記事のほとんどのコードがハイライト(色分け)されておらず、見にくく感じます。細かい点ですが、気になる点です。

総評

4つデメリットを挙げてみましたが、全体的にsvelteを使用しているユーザー数が少ないことに起因する問題が大きいと感じます。
1.の情報が少ないは、ユーザー数が少ない分情報を発信する人が少ないことが大きな原因と考えられます。2.のSvelte5以前と書き方が大きく異なる問題は、runeについての情報がインターネット上に多く出回ればそこまで大きな問題にはなりません。4.のハイライト問題もユーザー数が増えればライブラリ側で対応が進むと考えられます。
後述するように、Svelteはメリットも大きいと感じるので、もっと多くの人に使用されるフレームワークになってほしいところです。

2. メリット

1. 単純で直感的にコードが分かる

Svelteの強みの中でも一番大きいと考えられるのは、やはりその単純さです。
Reactで

const [count,setCount] = useEffect(0);

と書いていたものが、Svelteでは

let count = $state(0)

これだけで書くことができます。
ステートの更新も、Reactではset...(...)のように書く必要がありますが、svelteでは普通の代入構文で記述できます。特に、オブジェクトのステートなどスプレッド構文を駆使して更新していましたが、Svelteではその必要がありません。
コード量もSvelteは他のライブラリに比べて大幅に少なくなります。それだけ分かりやすいコードを書けるということです。
また、Svelte5以前のSvelteは、お世辞にも大規模なアプリケーションには向いているとは言えませんでしたが、Svelte5でRuneを導入したことによりこの点も大きく改善したようです。
だらだらと説明を書いても分かりにくいと思うので実際のコードをお見せしましょう。🍎と🍌の個数を数えて、合計を表示するコンポーネントです。

svelte5(Runeあり)
<script>
    let apple = $state(0)
    let banana = $state(0)
    
    const countUpApple = () => apple += 1;
    const countUpBanana = () => banana += 1;
    
    let sum = $derived(apple+banana);
</script>

<button onclick={countUpApple}>🍎りんご:{apple}</button>
<button onclick={countUpBanana}>🍌バナナ:{banana}</button>
<p>合計 : {sum}</p>
svelte5以前(Runeなし)
<script>
    let apple = 0
    let banana = 0
    
    const countUpApple = () => apple += 1;
    const countUpBanana = () => banana += 1;
    
    $: let sum = apple+banana;
</script>

<button onclick={countUpApple}>🍎りんご:{apple}</button>
<button onclick={countUpBanana}>🍌バナナ:{banana}</button>
<p>合計 : {sum}</p>
React
import React, {useState, useMemo} from 'react';

export default function App() {
  const [apple, setApple] = useState(0);
  const [banana, setBanana] = useState(0);

  const countUpApple = () => setApple((apple) => apple + 1);
  const countUpBanana = () => setBanana((banana) => banana + 1);

  const sum = useMemo(() => apple + banana, [apple, banana])

  return (
    <>
      <button onClick={countUpApple}>🍎りんご:{apple}</button>
      <button onClick={countUpBanana}>🍌バナナ:{banana}</button>
      <p>合計 : {sum}</p>
    </>
  );
}

SvelteのコードがReactと比べ簡潔で理解しやすい物であることは一目瞭然です。
また、RuneありのコードはRuneなしのコードと比べてわざわざ変数を$effect()で囲っていたり、無駄な記述が増えたように感じます。なぜこのような変更をしたのかと言うと、もともとRuneなしの書き方は、特に複雑なアプリケーションにおいて、どの値がリアクティブでどの値がリアクティブでないか開発者を混乱させるものでした。Runeはこのような問題を解決するために登場したものです。実際に使って見ましたが、特に難しいところもなく、以前の書き方に慣れている開発者でもすぐに書くことができるようになると思います。

2. 軽い

コンパイルを行い最適化されたコードを使用するためか、Next.jsにくらべてかなり軽く感じます。仮想DOMを使用しないということも関係しているのでしょうか?詳細はわかりませんが、かなり軽いです。
また、驚いたのがビルド時の速度です。以下、全く同じサイトで比べたわけでは無いので単純比較はできませんが、Next.jsでは少なくとも30秒はかかっていたビルドがsveltekitでは5秒もかかりませんでした。
ビルド後も、特に動的ルーティングを設定しているページでは表示にかかる速度が大きく違うと感じています。

3. ファイル整理がしやすい

別にsvelteに限った話ではありませんが、HTML部分とCSS部分、JS部分を.svelteという一つのファイルにまとめる事で、ファイルの管理が楽になったと感じました。
とは言っても、Reactの場合インラインでCSSを書けば全く同じ事が出来ます。さらに、Vue.jsでも.vueという拡張子のファイルを使用するという似たようなアプローチをとっているのでそこまで特筆するほどの話では無いかもしれません。
ただ、これまでReactのモジュールCSSを使用してた身からしてみると、感動した要素の一つなので、一応書いておきます。

まとめ

何回も同じようなことを繰り返し言っていますが、Svelteは情報が少ないです。しかし、フレームワークとしての完成度はかなり高いです。また簡潔な文法である分、慣れるまでが早いです。そして、慣れてしまえばある程度のデメリットは気にならなくなります。
ということで、気になった方は是非使ってみて下さい。
また、Sveltekitを使用して作成した2(MhYg)もよろしくおねがいします。

Discussion

ログインするとコメントできます