SvelteKitのレイアウト(+layout.svelte)を深掘りした話

SvelteKitの +layout.svelte の応用パターンを整理します。ネストしたレイアウト・レイアウトデータの取得・ルートグループ・レイアウト無効化を解説します。


レイアウトの基本的な仕組みのおさらい

src/routes/
  +layout.svelte    ← 全ページ共通のレイアウト
  +page.svelte      ← / のコンテンツ
  posts/
    +layout.svelte  ← /posts 配下だけに適用されるレイアウト
    +page.svelte    ← /posts のコンテンツ
    [id]/
      +page.svelte  ← /posts/[id] のコンテンツ

子のレイアウト・ページは親のレイアウトの {@render children()} の位置に差し込まれます。


① レイアウトデータを load で渡す

+layout.server.ts を使うと全ページで共通のデータを取得できます。ログインユーザー情報の取得が典型例です。

// src/routes/+layout.server.ts
import type { LayoutServerLoad } from './$types';

export const load: LayoutServerLoad = async ({ locals }) => {
  return {
    user: locals.user ?? null,
  };
};
<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import type { Snippet } from 'svelte';
  import type { LayoutData } from './$types';

  type Props = {
    data: LayoutData;
    children: Snippet;
  };

  let { data, children }: Props = $props();
</script>

<header>
  {#if data.user}
    <span>{data.user.name}</span>
    <a href="/logout">ログアウト</a>
  {:else}
    <a href="/login">ログイン</a>
  {/if}
</header>

<main>
  {@render children()}
</main>

各ページの +page.svelte では data.user を自分でロードしなくても、親レイアウトが取得した値を引き継げます。


② ルートグループ — URLに影響しないグループ化

(グループ名) という形式のディレクトリはURLに含まれません。レイアウトだけを切り替えたいときに使います。

src/routes/
  (public)/           ← URLには含まれない
    +layout.svelte    ← ログイン不要ページ用レイアウト
    +page.svelte      ← /
    about/
      +page.svelte    ← /about
  (authed)/           ← URLには含まれない
    +layout.svelte    ← ログイン済みページ用レイアウト
    dashboard/
      +page.svelte    ← /dashboard
    settings/
      +page.svelte    ← /settings
<!-- src/routes/(authed)/+layout.svelte -->
<script lang="ts">
  import { redirect } from '@sveltejs/kit';
  import type { Snippet } from 'svelte';
  import type { LayoutData } from './$types';

  type Props = {
    data: LayoutData;
    children: Snippet;
  };

  let { data, children }: Props = $props();

  if (!data.user) {
    redirect(302, '/login');
  }
</script>

{@render children()}

ログイン必須ページをまとめてグループ化することで、認証チェックを1か所に集約できます。


③ レイアウトを無効化する

特定のページだけ親のレイアウトを使いたくない場合、ファイル名に @ を付けます。

src/routes/
  +layout.svelte
  login/
    +page@.svelte   ← ルートレイアウトを無効化(レイアウトなしで表示)

+page@.svelte は全レイアウトをスキップして素のページとして表示されます。ログインページや全画面表示のページで使います。


まとめ

機能 書き方 用途
共通レイアウト +layout.svelte ヘッダー・フッターなど
共通データ取得 +layout.server.ts ログインユーザー情報など
URLに影響しないグループ (グループ名)/ 認証あり・なしでレイアウトを分ける
レイアウト無効化 +page@.svelte ログインページなど

次の記事:SvelteKitの+layout.svelteと+page.svelteの役割の切り分けを整理した

← トップページに戻る