レイアウト
Edit this page on GitHubここまで、ページを完全に独立したコンポーネントとして扱ってきました — ナビゲーションを行うと、既存のコンポーネントは破棄され、新しいコンポーネントがその場所を引き継ぎます。
しかし、多くのアプリでは、トップレベルのナビゲーションやフッターなど、全てのページで表示されるべき要素が存在します。それらを全てのページで繰り返し書くのではなく、レイアウト(layout) コンポーネントを使うことができます。
全てのページに適用されるレイアウトを作るには、src/routes/__layout.svelte
というファイルを作成します。(自分で作成していない場合に使用される)デフォルトのレイアウトは、以下のようなものです…
<slot></slot>
…ですが、お好みのマークアップ、スタイル、動作を追加できます。ただし、コンポーネントがページコンテンツ用の <slot>
を含んでいる必要があります。例えば、ナビゲーションバー(nav bar)を追加してみるとしましょう。
src/routes/__layout.svelte
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/settings">Settings</a>
</nav>
<slot></slot>
/
、/about
、/settings
用のページを作成してみます…
src/routes/index.svelte
<h1>Home</h1>
src/routes/about.svelte
<h1>About</h1>
src/routes/settings.svelte
<h1>Settings</h1>
...nav は常に表示され、3つのページリンクをそれぞれクリックすると、<h1>
が置き換えられるだけです。
ネストレイアウト(Nested layouts)permalink
単一の /settings
ページを持つのではなく、/settings/profile
や /settings/notifications
といったページをネストして(※入れ子にして)サブメニューを共有するとします (実例としては、github.com/settings をご覧ください)。
(Topレベルの nav を持つルートレイアウト(root layout)を継承しつつ) /settings
以下のページにのみ適用されるレイアウトを作成することができます。
src/routes/settings/__layout.svelte
<h1>Settings</h1>
<div class="submenu">
<a href="/settings/profile">Profile</a>
<a href="/settings/notifications">Notifications</a>
</div>
<slot></slot>
名前付きレイアウト(Named layouts)permalink
アプリには、デフォルトのレイアウトとは違うレイアウトが必要になる部分もあるでしょう。そういったケースには、名前付きレイアウト(named layouts) を作成することができます…
src/routes/__layout-foo.svelte
<div class="foo">
<slot></slot>
</div>
…そしてレイアウトの名前(上記の例では foo
)をファイル名で参照することによってこれを使用します:
src/routes/my-special-page@foo.svelte
<h1>I am inside __layout-foo</h1>
名前付きレイアウト(Named layouts)はとてもパワフルですが、理解するのに少し時間がかかるかもしれません。一度に理解できなくても心配しないでください。
スコープ(Scoping)permalink
名前付きレイアウト(Named layouts)は任意の深さに作成することができ、同じサブツリーにあるどのコンポーネントにも適用されます。例えば、__layout-foo
は /x/one
と /x/two
に適用されますが、/x/three
や /four
には適用されません:
src/routes/
├ x/
│ ├ __layout-foo.svelte
│ ├ one@foo.svelte # ✅ `@foo` が付いているページ
│ ├ two@foo.svelte # ✅ `@foo` が付いているページ
│ └ three.svelte # ❌ `@foo` が付いていないページ
└ four@foo.svelte # ❌ `@foo` が付いているページだが、__layout-foo の 'スコープ内' ではない
継承チェーン(Inheritance chains)permalink
レイアウトは、同じディレクトリまたは親ディレクトリにある名前付きレイアウト(named layouts)を継承するかどうか選択できます。例えば、x/y/__layout@root.svelte
には名前が付いていないため、/x/y
のデフォルトのレイアウトです (つまり、/x/y/one
、/x/y/two
、/x/y/three
はどれもこのレイアウトを継承します)。@root
を指定しているため、もっとも近くにある __layout-root.svelte
を直接継承することになり、__layout.svelte
と x/__layout.svelte
をスキップします。
src/routes/
├ x/
│ ├ y/
│ │ ├ __layout@root.svelte
│ │ ├ one.svelte
│ │ ├ two.svelte
│ │ └ three.svelte
│ └ __layout.svelte
├ __layout.svelte
└ __layout-root.svelte
__layout-root.svelte
が単独の<slot />
のみを含んでいる場合、アプリ内のネストレイアウト(nested layout)に@root
を付けることで、任意のページをブランクレイアウトに 'リセット' することができます。
親が指定されていない場合、レイアウトはツリー上もっとも近くにあるデフォルトのレイアウト(つまり名前が付いていないレイアウト)を継承することになります。名前付きレイアウト(named layout)がツリー上一緒に並んでいるデフォルトのレイアウトを継承するので便利です。例えば、__layout-root.svelte
は __layout.svelte
を継承します。明示的に @default
を指定することで、/x/y/one
や同じ階層にあるページがアプリのデフォルトのレイアウトを使用するのに x/__layout.svelte
を使う必要がなくなります:
src/routes/
├ x/
│ ├ y/
│ │ ├ __layout@root.svelte
│ │ ├ one.svelte
│ │ ├ two.svelte
│ │ └ three.svelte
│ └ __layout.svelte
├ __layout.svelte
└ __layout-root.svelte
└ __layout-root@default.svelte
default
は予約済の名前です。言い換えると、__layout-default.svelte
というファイルを使用することはできないということです。
エラーページpermalink
ページがロード(Loadingを参照)に失敗した場合、SvelteKitはエラーページ(error page)をレンダリングします。レイアウトやページと一緒に __error.svelte
コンポーネントを作ることで、このページをカスタマイズすることができます。
例えば、src/routes/settings/notifications/index.svelte
でロードに失敗した場合、src/routes/settings/notifications/__error.svelte
が存在すればSveltekitはそれを同じレイアウトでレンダリングします。もし存在しなければ、src/routes/settings/__error.svelte
を親のレイアウトでレンダリングします。もしそれも存在しなければ、 src/routes/__error.svelte
をルートレイアウト(root layout) でレンダリングします。
SvelteKit はデフォルトのエラーページを提供してますが、ご自身で
src/routes/__error.svelte
を用意することを推奨します。
エラーコンポーネントに load
関数がある場合、error
プロパティと status
プロパティが引数に渡されて呼び出されます。
<script context="module">
/** @type {import('@sveltejs/kit').Load} */ export function load({ error, status }) {
return {
props: {
title: `${status}: ${error.message}`
}
};
}
</script>
<script>
export let title;
</script>
<h1>{title}</h1>
レイアウトでは、page store を使って
error
とstatus
にアクセスすることもできます。ユーザーに特権的な情報が公開されないようにするため、本番環境では
error
からサーバーサイドのスタックトレースが取り除かれます。
404spermalink
特定のページをレンダリングしているときにエラーが発生した場合のみ、ネストしたエラーページがレンダリングされます。リクエストがどのルートにもマッチしない場合、SvelteKitは代わりに一般的な 404 をレンダリングします。例えば、このようなルートの場合…
src/routes/
├ __error.svelte
├ marx-brothers/
│ ├ __error.svelte
│ ├ chico.svelte
│ ├ harpo.svelte
│ └ groucho.svelte
… /marx-brothers/karl
をリクエストしたとしても marx-brothers/__error.svelte
ファイルはレンダリングされません。ネストしたエラーページをレンダリングさせるには、/marx-brothers/*
に対するどんなリクエストにもマッチするようなルート(route)を作成し、そこから 404 を返すようにしてください:
src/routes/
├ __error.svelte
├ marx-brothers/
│ ├ __error.svelte
│ ├ [...path].svelte
│ ├ chico.svelte
│ ├ harpo.svelte
│ └ groucho.svelte
src/routes/marx-brothers/[...path].svelte
<script context="module">
/** @type {import('./__types/[...path]').Load} */ export function load({ params }) {
return {
status: 404,
error: new Error(`Not found: /marx-brothers/${params.path}`)
};
}
</script>