
SvelteKit のルーティングとファイル構造を理解する
+page.svelte から +server.ts まで全ファイルの役割を一気に把握する
SvelteKit のファイルベースルーティングを基礎から解説。+page.svelte・+layout.svelte・+page.server.ts・+server.ts など全ファイルの役割と配置ルールを商品カタログアプリの実装を通じて学びます。
シリーズ:SvelteKit サーバー・クライアント動作入門
01
ルーティングとファイル構造
02
データ取得:load と API Route
03
サーバーとクライアントの境界
「SvelteKitのプロジェクトを作ったら、src/routes/ の中にいろんなファイルがある。+page.svelte と+page.server.ts は何が違うんだろう?」
このシリーズは、そんな疑問を持った方に向けたものです。SvelteKitは 「ファイルを置く場所と名前」がそのままURLとサーバー/クライアントの動作を決める という設計になっています。このルールを最初にしっかり理解しておくと、あとの開発がずっとスムーズになります。
第1回では、SvelteKitに登場する全ファイルの役割と配置ルールを一気に把握します。詳細は第2回・第3回で順番に深掘りしますが、まずは「全体地図」を頭に入れましょう。
🛒 このシリーズで作るサンプルアプリ:商品カタログ(ECの簡易版)
3回を通して、以下の画面を持つ商品カタログアプリを段階的に育てていきます。今回はプロジェクトのセットアップとファイル構造の把握までを行います。
商品一覧ページ/products
商品詳細ページ/products/[id]
マイページ/mypage
商品API/api/products
SvelteKitとは何か
SvelteKitは、UIライブラリ「Svelte」をベースにした フルスタックWebフレームワーク です。Next.js(React)やNuxt(Vue)と同じポジションに相当します。バージョン2.x系が現在の安定版です。
SvelteKitの大きな特徴のひとつが 「ファイルベースルーティング」 です。src/routes/ 以下にファイルを置くだけで、URLのルーティングとサーバー/クライアントの動作が決まります。設定ファイルをほとんど書く必要がありません。
| フレームワーク | ベースUI | ルーティング | データ取得 |
|---|---|---|---|
| SvelteKit | Svelte | ファイルベース | load関数 / +server.ts |
| Next.js | React | ファイルベース | getServerSideProps / Route Handler |
| Nuxt | Vue | ファイルベース | useFetch / server/api/ |
💡 前提条件
このシリーズはNode.js(v18以上)とnpm/pnpmがインストールされていれば進められます。Svelteの基本的な構文({#if} /{#each} など)を知っていると読みやすいですが、必須ではありません。
プロジェクトを作成する
まず商品カタログアプリの土台となるSvelteKitプロジェクトを作成します。
$ npx sv create svelte-shop
┌ Welcome to the Svelte CLI!
│
◆ Which template would you like?
│ ● SvelteKit minimal
│
◆ Add type checking with Typescript?
│ ● Yes, using Typescript syntax
│
◆ What would you like to add to your project?
│ ◻ prettier ◻ eslint ◻ vitest ...(任意)
└
$ cd svelte-shop
$ npm install
$ npm run dev
▸ Local: http://localhost:5173/✨ sv create について
SvelteKit 2.x では公式CLIがcreate-svelte からsv に移行しています。npx sv create が最新の推奨コマンドです。テンプレートは SvelteKit minimal 、型チェックは TypeScript を選択してください。
生成されたファイル構造を見る
プロジェクトを作成すると、以下のようなファイルが生成されます。今は全部を理解しなくて大丈夫です。src/routes/ の中身に注目してください。
svelte-shop/
├─ src/
│ ├─ routes/ ← ルーティングのルート
│ │ ├─ +page.svelte ← / のページ
│ │ └─ +layout.svelte ← 全ページ共通レイアウト
│ ├─ app.d.ts ← 型定義ファイル
│ └─ app.html ← HTMLテンプレート
├─ svelte.config.js
├─ vite.config.ts
└─ package.json このsrc/routes/ の中に、これから複数のファイルを追加していきます。
ファイルベースルーティングの基本
SvelteKitでは、src/routes/ 以下のフォルダ構造がそのままURLになります。ルールはシンプルで、 フォルダ名がURLのパスになり、その中に置くファイル名がそのページの動作を決めます。
フォルダ構造とURLの対応
DIRECTORY URL
src/routes/ ------> (フォルダ自体は表示されない)
└─ +page.svelte ------> /
└─ products/ ------> (フォルダ)
├─ +page.svelte ------> /products
└─ [id]/ ------> (フォルダ)
└─ +page.svelte ------> /products/123
注目してほしいのは フォルダ名がURLになる という点です。ファイル名(+page.svelte )はURLには反映されません。URLになるのはあくまでフォルダ名です。
動的ルートセグメント(パラメータ)
[id] のように角括弧で囲んだフォルダ名は 動的ルートセグメント になります。/products/1 でも/products/abc でもマッチし、その値をコード内で取得できます(詳しくは第2回で扱います)。
| フォルダ構造 | マッチするURL例 |
|---|---|
| routes/ | / |
| routes/products/ | /products |
| routes/products/[id]/ | /products/1 /products/abc |
| routes/api/products/ | /api/products |
| routes/(shop)/mypage/ | /mypage (グループは無視) |
📌 ルートグループ:(グループ名) とは
丸括弧で囲んだフォルダ名(例:(shop) )は ルートグループ といい、URLには現れません。レイアウトを共有したいページをグループにまとめるために使います。このシリーズでは第1回の終盤で実際に使います。
全ファイルの役割を一覧で把握する
SvelteKitのルートディレクトリには、名前が決まった特殊ファイルを置きます。名前の先頭が+ になっているものがそれです。以下が全種類の一覧です。
+page.svelte
そのURLで表示される ページコンポーネント 。必須ファイル。ブラウザとサーバー両方でレンダリングされる(SSR)。
第1回で作成
/products/+page.svelte → /products のページ
+layout.svelte
そのフォルダ以下の全ページに 共通するレイアウト 。ヘッダー・フッター・ナビゲーションを置く。<slot /> の位置に子ページが挿入される。
第1回で作成
ネスト可能。複数階層に置ける。
+page.ts
ページに渡す データの取得ロジック(universal load) 。サーバーでもブラウザでも実行される。外部APIへのフェッチなど秘密情報を使わない処理に向く。
第2回で作成
export function load() を定義する
+page.server.ts
ページに渡すデータの取得ロジック( サーバー専用 load )。 サーバーでのみ実行 されるため、DBアクセスや秘密鍵を安全に使える。
第2回で作成
.server.ts の意味は第3回で解説
+layout.ts
レイアウト用の データ取得ロジック(universal) 。そのレイアウト配下の全ページで使えるデータを取得する。ナビゲーションに必要なカテゴリ一覧など。
第2回で作成
+page.ts と同じ書き方
+layout.server.ts
レイアウト用の データ取得ロジック(サーバー専用) 。認証情報など全ページで必要なサーバーサイドデータの取得に使う。
第2回で作成
認証チェックの定番パターン
+server.ts
REST APIエンドポイント 。GET / POST / PUT / DELETE などのHTTPメソッドに対応した関数をエクスポートする。ページUIは持たない純粋なAPIとして機能する。
第2回で作成
/api/products → routes/api/products/+server.ts
+error.svelte
そのルート以下で エラーが発生したときに表示されるページ 。404や500などのエラーをカスタマイズできる。置いていない場合はSvelteKitのデフォルトエラーページが表示される。
第3回で作成
エラーハンドリングの全体像と合わせて解説
💡 ファイル名の「+」の意味
先頭の+ は「SvelteKitが特別扱いするファイル」であることを示すプレフィックスです。この命名規則のおかげで、同じフォルダに置いた通常のutils.ts やcomponents/Card.svelte などのファイルと区別できます。+ なしのファイルはルーティングに影響しません。
レイアウトの継承とネスト
SvelteKitのレイアウトは フォルダの階層に沿って入れ子(ネスト)になります。 これがSvelteKitの強力な機能のひとつで、「このセクションだけ別のレイアウトを使いたい」という要求を自然に実現できます。
ネストの仕組み
商品カタログアプリで例えると、以下のような3階層のレイアウトを構成できます。
src/routes/+layout.svelte ← ルートレイアウト(全ページ共通)
サイト全体のヘッダー・フッターを持つ。すべてのページがこの中に入る。
<slot /> ← 子レイアウト or 子ページが入る位置
src/routes/(shop)/+layout.svelte ← ショップセクション用レイアウト
カート情報・カテゴリナビなど、ショップ画面だけに必要なUIを追加。
<slot /> ← 各ページが入る位置
src/routes/(shop)/products/+page.svelte ← 商品一覧ページ
商品のグリッド表示など、このページ固有のコンテンツ。
ルートレイアウト → セクションレイアウト → ページの順で入れ子になります。ユーザーが/products にアクセスすると、SvelteKitは自動的に3つを組み合わせてHTMLを生成します。
⚠️ ️ レイアウトをリセットしたい場合
特定のページでは親レイアウトを完全に無視したい(例:ログインページ)場合、ファイル名を+page@.svelte とすることでルートレイアウトのみを使うようリセットできます。詳しくは公式ドキュメントの「Breaking out of layouts」を参照してください。
商品カタログのルート構造を作る
理解を定着させるために、実際にファイルを作ってブラウザで動く状態にしましょう。今回は ページの中身(データ取得)は仮のもの で構いません。ルーティングとレイアウトの動作確認に集中します。
目標のファイル構造
src/routes/
├─ +layout.svelte ← 全体共通(ヘッダー)
├─ +page.svelte ← / (トップページ)
├─ (shop)/ ← ルートグループ(URLに出ない)
│ ├─ +layout.svelte ← ショップ共通(カテゴリナビ)
│ ├─ products/
│ │ ├─ +page.svelte ← /products
│ │ └─ [id]/
│ │ └─ +page.svelte ← /products/[id]
│ └─ mypage/
│ └─ +page.svelte ← /mypage
└─ api/
└─ products/
└─ +server.ts ← /api/products(第2回で実装)
各ファイルを作成する
まず全体共通のルートレイアウトを作ります。
<script lang="ts">
</script>
<header>
<nav>
<a href="/">SvelteShop</a>
<a href="/products">商品一覧</a>
<a href="/mypage">マイページ</a>
</nav>
</header>
<!-- この slot に各ページが挿入される -->
<main>
<slot />
</main>次に、ショップセクション用のレイアウトを作ります。
<script lang="ts">
</script>
<!-- カテゴリナビ(第2回でデータを繋げる) -->
<aside>
<ul>
<li><a href="/products">すべての商品</a></li>
</ul>
</aside>
<section>
<slot />
</section>続いて商品一覧ページを作ります。
<script lang="ts">
// 第2回でデータ取得を実装します
</script>
<h1>商品一覧</h1>
<p>ここに商品が表示されます(第2回で実装)</p> 商品詳細ページを作ります。動的ルートなので[id] フォルダの中に置きます。
<script lang="ts">
// URLの [id] パラメータの取得は第2回で解説します
</script>
<h1>商品詳細</h1>
<p>ここに商品の詳細が表示されます(第2回で実装)</p>マイページを作ります。
<script lang="ts">
// 認証情報の取得は第2回・第3回で実装します
</script>
<h1>マイページ</h1>
<p>ログイン中のユーザー情報がここに表示されます(第2回で実装)</p> 動作確認
npm run dev で開発サーバーを起動して、各URLにアクセスして確認します。
http://localhost:5173/ → トップページ
http://localhost:5173/products → 商品一覧(ショップレイアウト適用)
http://localhost:5173/products/1 → 商品詳細(ショップレイアウト適用)
http://localhost:5173/mypage → マイページ(ショップレイアウト適用)🎯 確認できること
/products や/mypage にアクセスしたとき、ルートレイアウトのヘッダーとショップレイアウトのカテゴリナビが両方表示されているはずです。これがネストしたレイアウトの動作です。
また/products/1 でも/products/999 でも同じページが表示されることも確認してください([id] が動的ルートとして機能している)。
ファイル命名規則の全体像まとめ
ここまでのファイルをまとめて、「どこで動くか」という観点で整理します。これはこのシリーズ全体を通じて繰り返し参照することになる重要な表です。
| ファイル名 | 動く場所 | 主な用途 | 詳解 |
|---|---|---|---|
+page.svelte | サーバー+ブラウザ | ページのUIコンポーネント | 第1回 |
+layout.svelte | サーバー+ブラウザ | 共通レイアウト(ヘッダー・ナビなど) | 第1回 |
+page.ts | サーバー+ブラウザ | ページへのデータ取得(universal load) | 第2回 |
+page.server.ts | サーバーのみ | DBアクセス・秘密鍵を使うデータ取得 | 第2回 |
+layout.ts | サーバー+ブラウザ | レイアウト用データ取得(universal load) | 第2回 |
+layout.server.ts | サーバーのみ | 認証情報など全ページ共通のサーバーデータ | 第2回 |
+server.ts | サーバーのみ | REST APIエンドポイント(GET / POST等) | 第2回 |
+error.svelte | サーバー+ブラウザ | エラーページのUI(404・500など) | 第3回 |
💡 .server.ts の意味
ファイル名に.server が含まれていると、SvelteKitはそのファイルをブラウザに送信しません。DBのパスワードやAPIシークレットキーを書いても外部に漏れない仕組みです。詳しくは第3回「サーバーとクライアントの境界」で解説します。
第1回のまとめ
今回学んだこと
- SvelteKitは
src/routes/以下のフォルダ構造がURLになる ファイルベースルーティング を採用している [id]フォルダで動的ルートセグメントを表現できる+page.svelteがページ、+layout.svelteが共通レイアウト ― レイアウトは階層に沿ってネストする(グループ名)フォルダはURLに現れず、レイアウトのグループ化に使う+page.server.ts/+server.tsなど .server がつくファイルはサーバーでしか動かない- 全ファイルの役割を概観した ― データ取得の詳細は第2回、サーバー/クライアントの境界は第3回で深掘りする
- 本番で見せたくないルートは、ファイル配置や
hooks.server.tsで制御する
📌 第1回のまとめ
SvelteKitの「ファイル名とフォルダ構造がすべてを決める」という設計思想が理解できました。今回作った商品カタログのルート構造は、次回以降で実際のデータ取得を繋げていく土台になります。次回は+page.server.ts のload 関数を中心に、 ページにデータを渡す3つの方法と使い分け を学びます。
