【SvelteKit】ルーティングとローディングとレイアウト

SvelteKit はファイルシステムベースのルーティングが採用されており、src/routesディレクトリ内に+page.svelteファイルを作成することでページが作成されます。

以下のディレクトリ構成はHome(root)ページとAboutページ・Itemの一覧ページを作った例です。

src/routes
 ├ +layout.svelte
 ├ +page.svelte
 ├ about
 │  └ +page.svelte
 └ items
    ├ +page.server.ts
    ├ +page.svelte
    ├ data.ts   <- データベースの代わり
    └ [id]
       ├ +error.svelte
       ├ +page.server.ts
       └ +page.svelte

レイアウト

ナビゲーションなど全ページ共通して設置したいものは+layout.svelteファイルに書き込みます。

<slot />要素は、ページコンテンツが表示される場所

<nav>
  <a href="/">Home</a>
  <a href="/about">About</a>
  <a href="/items">Items</a>
</nav>

<slot />

静的ルーティング

以下のディレクトリにそれぞれ+page.svelteファイルを作成します。
//aboutのそれぞれのページが作成されアクセスできるようになります。

  • src/routes:最上位(/)のルート
  • src/routes/about:/aboutのルート
<h1>Home</h1>
<h1>About</h1>

動的ルーティングとローディング

src/routes/items/[id]のように角括弧([])で変数名を囲むことで、動的なパラメーター付きのルートを作ることができます。

+page.svelteファイルと同ディレクトリに+page.server.tsファイルを設置し、load関数を宣言することでデータを取得し、ルートに渡すことができます。

本来はデータベースなどから取得するものですが、以下のファイルからデータをインポートします。

export const items = [
    {
        id: '001',
        name: 'item1',
    },
    {
        id: '002',
        name: 'item2',
    },
    {
        id: '003',
        name: 'item3',
    },
    {
        id: '004',
        name: 'item4',
    },
    {
        id: '005',
        name: 'item5',
    },
]

src/routes/items 階層

import { items } from './data';


export function load() {
  return {
    summaries: items.map((item) => ({
      id: item.id,
      name: item.name,
    }))
  };
}
<script lang='ts'>
  import type { PageData } from './$types.js';
  export let data: PageData;
</script>

<h1>Items</h1>
<ul>
  {#each data.summaries as { id, name }}
    <li><a href="/items/{id}">{name}</a></li>
  {/each}
</ul>

src/routes/items/[id] 階層

import type { PageServerLoad } from './$types';
import { error } from '@sveltejs/kit';
import { items } from '../data';


export const load = (async ({ params }) => {
  const item = items.find((item) => item.id === params.id);

  if (item) {
    return {item};
  }
  throw error(404, 'Not found');
}) satisfies PageServerLoad;
<script>
  export let data;
</script>

<h1>{data.item.name}</h1>

エラーページ

通常はデフォルトのエラーページが表示されるので、〇〇へ戻るなど追加したい場合は+error.svelteファイルを追加することでルートごとにエラーページをカスタマイズできます。

<script>
  import { page } from '$app/stores';
</script>

<h1>{$page.status}: {$page.error?.message}</h1>
<a href="/items">Item一覧へ戻る</a>