もしここ数年、メタフレームワークの間を渡り歩いてきたのであれば、SvelteKit 2は安堵と疑念が入り混じった不思議な感覚をもたらすでしょう。安堵、それは複雑さを増やすのではなく、実際に複雑さを取り除いてくれるからです。疑念、それは「何か落とし穴があるのではないか」と待ち構えてしまうからです。しかし、実際には何も起こりません。Svelte 5と組み合わせることで、このスタックは2026年においてフルスタックアプリケーションを構築するための最も生産的な方法の一つとなり、その開発者体験(DX)の良さは数値にも表れています。バンドルサイズはSvelte 4の時よりも約35%小さくなっています。ルーティング、サーバー関数、認証パターンはすべて、継ぎ接ぎで作るプラグインではなく、ファーストクラスの機能として提供されています。

ルーン(Runes)によってリアクティビティが明示的になる

最大の思考の転換は、Svelte 5の「ルーン(runes)」からもたらされます。以前のバージョンのSvelteでは、$: ラベルと多くのコンパイラの魔法を使用して依存関係を追跡していました。それは機能していましたが、何かが壊れたとき、あなたは「見えない配線」をデバッグすることになっていました。ルーンは、その魔法を明示的な関数に置き換えます。何を追跡すべきかをコンパイラに正確に伝えることで、コンパイラがそれを正確に聞き取ってくれるようになります。

知っておくべきことは以下の通りです。

  • $state はリアクティブな変数を扱います。値を $state() でラップするだけで、コンパイラはそれを監視対象として認識します。
  • $derived は他のステートから値を計算します。フィルタリングされたリストや、フォーマット済みの合計値が必要ですか?その場合は $derived を使用してください。$effect との主な違いは、$derived は「値」のためのものであり、「アクション」のためのものではないという点です。
  • $effect はサイドエフェクトを実行します。ドキュメントタイトルの更新、手動でのDOM計測、クリーンアップが必要なタイマーなどを想定してください。これはDOMがコミットされた後に実行されます。ライフサイクルフックに似ていますが、特定のリアクティブな依存関係に紐付いています。
  • $props は、コンポーネントでデータを受け取るための従来の export let パターンに代わるものです。より明確であり、TypeScriptとの親和性も高まっています。

このモデルは、実務において大きな恩恵をもたらします。コンパイラはマークされたものだけを追跡するため、デッドコードが不要な追跡対象として残ることはありません。なぜ変数が更新をトリガーしたのかと悩む代わりに、自分自身の明示的な指示を信頼できるようになります。

設定ではなく、フォルダによるルーティング

SvelteKitは、ルーティングにファイルシステムを使用します。管理すべき個別のルーターファイルは存在しません。ディレクトリに +page.svelte ファイルを置くだけで、そのディレクトリがライブなルートになります。

共有UIは、+layout.svelte を通じてそれらのルートをラップします。ルートに配置すれば、すべてのチャイルドルートがそれを継承します。ツリーのより深い位置に配置すれば、そのセクションのみがラッパーを受け取ります。

サーバーサイドのロジックは +page.server.ts に記述します。これはページがレンダリングされる前に実行されるため、データベースへのクエリ、クッキーの検証、未認証ユーザーの拒否などを行うのに適しています。型は load 関数からページコンポーネントへと自動的に流れるため、手動でインターフェースを書かなくてもデータに型が付与されます。

生のAPIエンドポイントは +server.ts ファイルに配置します。これらは標準的なHTTPハンドラー(GET、POST、PUT、DELETE)をエクスポートするため、ページと並行してRESTバックエンドを構築することが自然に行えます。

見落とされがちな機能として、「ルートグループ」があります。フォルダ名を (auth) のように括弧で囲むことで、URLにセグメントを追加することなく共有レイアウトを作成できます。これは、/auth/login ではなく /login/signup というURLを持ちつつ、同じ最小限のUI構成が必要なログイン・サインアップページに最適です。

データ、セキュリティ、そしてプログレッシブ・エンハンスメント

モダンなフレームワークは「フルスタック」について語るのが大好きですが、認証チェックやフォームロジックをどこに置くべきか迷わせることが多々あります。SvelteKitは明確なフックを提供します。

データのフェッチには +page.server.ts を使用してください。そこにある load 関数はサーバー上でのみ実行されるため、データベースの認証情報がブラウザに漏洩することはありません。SvelteKitは load 関数の戻り値から型を生成するため、フロントエンドの型安全性も保たれます。

アプリケーション全体を制御するには hooks.server.ts を使用します。これはすべてのリクエストで実行されるため、セッションの検証、JWTの有効期限チェック、あるいはリクエストイベントへのユーザーコンテキストの付与を行うのに最適な場所です。

ミューテーション(データの更新)には、フォームアクションを使用します。個別のAPIエンドポイントを構築してJSONを扱う代わりに、+page.server.ts 内にアクションを定義します。ここでの素晴らしさは「プログレッシブ・エンハンスメント」です。もしJavaScriptの読み込みに失敗した場合や、ユーザーがJavaScriptを無効にしている場合でも、フォームはサーバーアクションに送信され、ページは結果とともに再レンダリングされます。JavaScriptが利用可能な場合は、SvelteKitがフルリロードなしで体験を強化(enhance)します。同じコードから、弾力性と洗練された体験の両方を得られるのです。

覚えておくべきルールが一つあります。計算は $effect ではなく $derived で行ってください。値を計算するために $effect を使用すると、追跡が困難な更新ループを引き起こす可能性があります。$effect は真のサイドエフェクトのために残し、計算されたステートは $derived に任せましょう。

SvelteKit versus Next.js

両方のフレームワークともプロダクション環境向けのアプリケーションをリリースできますが、トレードオフは確実に存在します。

バンドルサイズに関しては SvelteKit が有利です。Svelte はコンポーネントを vanilla JavaScript にコンパイルし、Virtual DOM を完全にスキップするため、ランタイムのフットプリントが小さく抑えられます。Next.js は React の reconciliation エンジンを伴います。

リアクティビティも異なります。SvelteKit はコンパイル時に runes を解決します。ブラウザにはプレーンな更新が届きます。Next.js は React のランタイムフックと reconciliation に依存しているため、クライアント側で行われる処理が多くなります。

SvelteKit の方がオンボーディングが容易です。メンタルモデルがよりシンプルだからです。再レンダリングを避けるために useEffect の依存関係配列やメモ化のパズルに頭を悩ませる必要はありません。TypeScript の統合についても触れておくべきでしょう。両方のフレームワークとも