SvelteKit
シンプルで高速なWebアプリケーションフレームワーク
SvelteKitとは?
日常での例え:「家具付きマンション」
自由だけど、家を建てる道具も
材料も全部自分で用意が必要
ルーティング、データ取得、ビルド設定...
必要なものが最初から揃っている
「フレームワーク」とは?なぜ使う?
フレームワーク= Webアプリを作るための「土台」や「骨組み」
フレームワークなしで作ると:
- ページ遷移の仕組みを自作する必要がある
- ビルド設定(Webpack等)を自分で書く必要がある
- SEO対策、パフォーマンス最適化も全部自分で
SvelteKitなら:これらが最初から用意されている!コードを書くことに集中できる
SvelteとSvelteKitの違い
Svelte:UIコンポーネントを作るためのライブラリ
SvelteKit:Svelteを使ったアプリを作るためのフレームワーク(ルーティング、ビルド等含む)
例えるなら:Svelte = レンガ、SvelteKit = レンガで家を建てる設計図と道具セット
SvelteKitでできること
高速パフォーマンス
特徴コンパイル時に最適化、小さなバンドル
ファイルベースルーティング
基本routes/フォルダがそのままURL
シンプルな構文
特徴学習コストが低く、直感的
リアクティビティ
Svelte 5$stateで状態管理が簡単
load関数
重要サーバーでデータ取得
Form Actions
便利フォーム処理が簡単
コード例
プロジェクト作成
npx sv createで開始
# プロジェクト作成
npx sv create my-app
# 開発サーバー起動
cd my-app
npm install
npm run dev基本的なページ
Svelteコンポーネントの構造
<!-- routes/+page.svelte -->
<script>
let count = $state(0);
function increment() {
count++;
}
</script>
<h1>Welcome to SvelteKit</h1>
<p>カウント: {count}</p>
<button onclick={increment}>+1</button>
<style>
h1 { color: #ff3e00; }
button {
padding: 8px 16px;
background: #ff3e00;
color: white;
border: none;
border-radius: 4px;
}
</style>Welcome to SvelteKit
カウント: 0
コード解説:Svelteファイルの3つの部分
① <script> - JavaScript(ロジック)
let count = $state(0):変数を作成(初期値0)
function increment():ボタンクリック時に呼ばれる関数
② HTML部分 - 画面表示
{count}:変数の値を表示(変数が変わると自動更新)
onclick={increment}:クリック時にincrement関数を実行
③ <style> - CSS(見た目)
このコンポーネント専用のスタイル。他のページには影響しません。
リアクティビティ(Svelte 5)
$stateと$derivedで状態管理
<script>
// リアクティブな状態
let count = $state(0);
let name = $state('');
// 派生値(countが変わると自動更新)
let doubled = $derived(count * 2);
// エフェクト(依存値が変わると実行)
$effect(() => {
console.log('Count changed:', count);
});
</script>
<input bind:value={name} placeholder="名前">
<p>こんにちは、{name || 'ゲスト'}さん</p>
<p>Count: {count}, Doubled: {doubled}</p>こんにちは、ゲストさん
Count: 0, Doubled: 0
コード解説:Svelte 5の「Runes」
$state - 変更を追跡する変数
この変数が変わると、使っている場所すべてが自動で再描画されます。
$derived - 他の値から計算される値
countが1になったら、doubledは自動的に2になります。手動で更新する必要なし!
bind:value - 双方向バインディング
入力欄に文字を打つとname変数が自動更新。nameを変えると入力欄の内容も変わります。
{name || "ゲスト"} - 条件付き表示
nameが空(未入力)の時は「ゲスト」を表示。入力があればその名前を表示します。
データ取得(load関数)
+page.server.tsでサーバーサイド取得
// routes/posts/+page.server.ts
export async function load() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return {
posts // ページコンポーネントで使える
};
}
// routes/posts/+page.svelte
<script>
let { data } = $props();
</script>
{#each data.posts as post}
<article>
<h2>{post.title}</h2>
</article>
{/each}記事タイトル1
記事タイトル2
コード解説:サーバーとページの連携
ステップ1:サーバー側でデータ取得(+page.server.ts)
export async function load():ページが開かれる前に実行される
await fetch(...):APIからデータを取得(サーバー側で実行)
return {posts}:取得したデータをページに渡す
ステップ2:ページ側でデータ受け取り(+page.svelte)
let {data} = $props():load関数が返したデータを受け取る
data.posts:load関数で return したpostsにアクセス
処理の流れ
1. ユーザーが /posts にアクセス → 2. load関数がサーバーで実行 → 3. APIからデータ取得 → 4. ページに渡される → 5. 画面表示
Form Actions
サーバーサイドでフォーム処理
// routes/login/+page.server.ts
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
const email = data.get('email');
const password = data.get('password');
// 認証処理...
return { success: true };
}
};
// routes/login/+page.svelte
<form method="POST">
<input name="email" type="email" required>
<input name="password" type="password" required>
<button type="submit">ログイン</button>
</form>レイアウト
+layout.svelteで共通UI
<!-- routes/+layout.svelte -->
<script>
let { children } = $props();
</script>
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
{@render children()}
</main>
<footer>
© 2024 My App
</footer>条件分岐とループ
Svelteのテンプレート構文
<script>
let items = $state(['りんご', 'バナナ', 'オレンジ']);
let show = $state(true);
</script>
<!-- 条件分岐 -->
{#if show}
<p>表示中</p>
{:else}
<p>非表示</p>
{/if}
<!-- ループ -->
<ul>
{#each items as item, index}
<li>{index + 1}. {item}</li>
{/each}
</ul>表示中
- 1. りんご
- 2. バナナ
- 3. オレンジ
コード解説:どのように動作するか
① 変数の準備(<script>内)
$state([...]) で配列を作成。これにより、配列が変更されると自動的に画面も更新されます。
② 条件分岐({#if} 〜 {/if})
<p>表示中</p> ← showがtrueの時に表示
{:else}
<p>非表示</p> ← showがfalseの時に表示
{/if}
show = true なので「表示中」が表示されています。
③ ループ({#each} 〜 {/each})
<li>{index + 1}. {item}</li>
{/each}
items の各要素を順番に処理:
item:現在の要素(「りんご」「バナナ」「オレンジ」)index:順番(0, 1, 2)→ +1して「1, 2, 3」として表示
結果の組み立て
配列を1つずつ処理して、<li>1. りんご</li>、<li>2. バナナ</li>、<li>3. オレンジ</li> が順番に生成されます。
ディレクトリ構造
my-app/
├── src/
│ ├── routes/
│ │ ├── +layout.svelte # 共通レイアウト
│ │ ├── +page.svelte # トップページ (/)
│ │ ├── about/
│ │ │ └── +page.svelte # /about
│ │ └── blog/
│ │ ├── +page.svelte # /blog
│ │ └── [slug]/
│ │ └── +page.svelte # /blog/:slug
│ ├── lib/
│ │ └── components/ # 再利用コンポーネント
│ └── app.html
├── static/ # 静的ファイル
└── package.json