SvelteKit の中心は、 _ファイルシステムベースのルーター_ です。アプリのルート(routes) — 例えばユーザーがアクセスできる URL パス — は、コードベースのディレクトリによって定義されます: - `src/routes` は最上位のルート(the root route)です - `src/routes/about` は `/about` ルート(route)を作成します - `src/routes/blog/[slug]` は _パラメータ_ `slug` を使ったルート(route)を作成します。パラメータは、ユーザーからのリクエストが `/blog/hello-world` のようなページに行われた場合に、動的にデータを読み込むために使用することができます > [!NOTE] [プロジェクトの設定](configuration) を編集することで、`src/routes` から別のディレクトリに変更することができます。 ルート(route)のディレクトリはそれぞれ1つ以上の _ルートファイル(route files)_ を格納します。ルートファイル(route files)には `+` という接頭辞が付いているので、それで見分けることができます。 We'll introduce these files in a moment in more detail, but here are a few simple rules to help you remember how SvelteKit's routing works: * All files can run on the server * All files run on the client except `+server` files * `+layout` and `+error` files apply to subdirectories as well as the directory they live in ## +page ### +page.svelte `+page.svelte` コンポーネントはアプリのページを定義します。デフォルトでは、ページは最初のリクエストではサーバー ([SSR](glossary#SSR)) でレンダリングされ、その後のナビゲーションではブラウザ ([CSR](glossary#CSR)) でレンダリングされます。 ```svelte

Hello and welcome to my site!

About my site ``` ```svelte

About this site

TODO...

Home ``` > [!NOTE] SvelteKit uses `` elements to navigate between routes, rather than a framework-specific `` component. Pages can receive data from `load` functions via the `data` prop. ```svelte

{data.title}

{@html data.content}
``` > [!LEGACY] > `PageProps` was added in 2.16.0. In earlier versions, you had to type the `data` property manually with `PageData` instead, see [$types](#\$types). > > Svelte 4 では、代わりに `export let data` を使用します ### +page.js ページではたびたび、レンダリングの前になんらかのデータを読み込む必要があります。これに対応するため、`load` 関数をエクスポートする `+page.js` モジュールを追加しています: ```js /// file: src/routes/blog/[slug]/+page.js import { error } from '@sveltejs/kit'; /** @type {import('./$types').PageLoad} */ export function load({ params }) { if (params.slug === 'hello-world') { return { title: 'Hello world!', content: 'Welcome to our blog. Lorem ipsum dolor sit amet...' }; } error(404, 'Not found'); } ``` この関数は `+page.svelte` とともに実行されます。サーバーサイドレンダリング中はサーバーで実行され、クライアントサイドナビゲーション中はブラウザで実行されます。API の詳細は [`load`](load) をご参照ください。 `+page.js` では、`load` だけでなくページの動作(behaviour)を設定するための値をエクスポートすることができます: - `export const prerender = true` または `false` または `'auto'` - `export const ssr = true` または `false` - `export const csr = true` または `false` これらに関するより詳しい情報は [page options](page-options) をご覧ください。 ### +page.server.js `load` 関数をサーバー上でのみ実行できるようにしたい場合 — 例えば、データベースからデータを取得したり、API キーのようなプライベートな[環境変数]($env-static-private)にアクセスしたりする必要がある場合 — `+page.js` を `+page.server.js` にリネームし、`PageLoad` 型を `PageServerLoad` に変更します。 ```js /// file: src/routes/blog/[slug]/+page.server.js // @filename: ambient.d.ts declare global { const getPostFromDatabase: (slug: string) => { title: string; content: string; } } export {}; // @filename: index.js // ---cut--- import { error } from '@sveltejs/kit'; /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { const post = await getPostFromDatabase(params.slug); if (post) { return post; } error(404, 'Not found'); } ``` クライアントサイドナビゲーション中は、SvelteKit はサーバーからこのデータを読み込みます。つまり、その戻り値は [devalue](https://github.com/rich-harris/devalue) によってシリアライズできなければならないということです。この API の詳細については [`load`](load) をご参照ください。 `+page.js` のように、`+page.server.js` は [page options](page-options) (`prerender`、`ssr`、`csr`) をエクスポートできます。 また、`+page.server.js` ファイルは _actions_ をエクスポートできます。`load` がサーバーからデータを読み取る場合、`actions` は `
` 要素を使用してサーバーにデータを書き込むことができます。これらの使い方を学ぶには、[form actions](form-actions) セクションをご参照ください。 ## +error `load` 中にエラーが発生した場合、SvelteKit はデフォルトのエラーページをレンダリングします。`+error.svelte` を追加することで、ルート(route) ごとにエラーページをカスタマイズすることができます: ```svelte

{page.status}: {page.error.message}

``` > [!LEGACY] > `$app/state` was added in SvelteKit 2.12. If you're using an earlier version or are using Svelte 4, use `$app/stores` instead. SvelteKit は、ツリーを上がって (walk up the tree) 最も近いエラー境界 (error boundary) を探します — もし上記のファイルが存在しない場合は、デフォルトのエラーページをレンダリングする前に `src/routes/blog/+error.svelte` を探しに行き、その次に `src/routes/+error.svelte` を探します。もしそれも失敗した場合は (または、最上位の `+error` の '上に' 位置する最上位の `+layout` の `load` 関数からエラーがスローされた場合)、SvelteKit は静的なフォールバックエラーページをレンダリングします。これは `src/error.html` ファイルを作成することでカスタマイズ可能です。 `+layout(.server).js` の `load` 関数の内側でエラーが発生した場合、ツリーの中で最も近くにあるエラー境界はそのレイアウトの上位にある `+error.svelte` ファイルです (隣ではありません)。 ルート(route)が見つからない場合 (404)、`src/routes/+error.svelte` (または、もしこのファイルが存在しない場合はデフォルトのエラーページ) が使われます。 > [!NOTE] エラーが [`handle`](hooks#Server-hooks-handle) の内側や [+server.js](#server) リクエストハンドラ の内側で発生した場合は、`+error.svelte` は使用されません。 エラーハンドリングに関する詳細は [こちら](errors) からお読み頂けます。 ## +layout これまで、ページを完全に独立したコンポーネントとして扱ってきました — ナビゲーションを行うと、既存の `+page.svelte` コンポーネントが破棄され、新しいページコンポーネントで置き換えられます。 しかし多くのアプリでは、トップレベルのナビゲーションやフッターのように _全ての_ ページで表示されるべき要素があります。全ての `+page.svelte` にそれらを繰り返し配置する代わりに、_レイアウト(layouts)_ に配置することができます。 ### +layout.svelte 全てのページに適用するレイアウトを作成するには、`src/routes/+layout.svelte` というファイルを作成します。デフォルトのレイアウト (あなたが作成していない場合に SvelteKit が使用するもの) は以下のようなものです… ```svelte {@render children()} ``` …しかし、お望みのマークアップ(markup)、スタイル(styles)、動作(behaviour)を追加することができます。唯一の要求事項は、コンポーネントにページコンテンツのための `@render` タグを含めることです。例えば、nav bar を追加してみましょう: ```svelte
{@render children()} ``` `/`、`/about`、`/settings` のためのページを作成する場合… ```html /// file: src/routes/+page.svelte

Home

``` ```html /// file: src/routes/about/+page.svelte

About

``` ```html /// file: src/routes/settings/+page.svelte

Settings

``` … nav は常に表示され、3つのページのための a 要素をそれぞれクリックしても `

` が置き換わるだけです。 レイアウトは _ネスト_ させることができます。例えば、単一の `/settings` ページだけでなく、`/settings/profile` や `/settings/notifications` のような共有のサブメニューを持つネストしたページがあるとします (実例としては、[github.com/settings](https://github.com/settings) をご参照ください)。 `/settings` 配下のページにのみ適用されるレイアウトを作成することができます (トップレベルの nav を持つ最上位のレイアウト(root layout)を継承しています): ```svelte

Settings

{@render children()} ``` > [!LEGACY] > `LayoutProps` was added in 2.16.0. In earlier versions, you had to [type the properties manually instead](#\$types). `data` がどのように入力されるかは、すぐ下の次のセクションにある `+layout.js` の例を見ればわかります。 デフォルトでは、各レイアウトはその上にあるレイアウトを継承します。そうしたくない場合は、[advanced layouts](advanced-routing#Advanced-layouts) が役に立つでしょう。 ### +layout.js `+page.svelte` が `+page.js` からデータを読み込むように、`+layout.svelte` コンポーネントは `+layout.js` の [`load`](load) 関数からデータを取得することができます。 ```js /// file: src/routes/settings/+layout.js /** @type {import('./$types').LayoutLoad} */ export function load() { return { sections: [ { slug: 'profile', title: 'Profile' }, { slug: 'notifications', title: 'Notifications' } ] }; } ``` `+layout.js` が [page options](page-options) (`prerender`、`ssr`、`csr`) をエクスポートする場合、それは子ページのデフォルトとしても使用されます。 レイアウトの `load` 関数から返されるデータは全ての子ページで利用することができます: ```svelte ``` > [!NOTE] しばしば、ページ間を移動しているときにレイアウトデータが変更されないことがあります。SvelteKit は必要に応じてインテリジェントに [`load`](load) 関数を再実行します。 ### +layout.server.js サーバー上でレイアウトの `load` 関数を実行するためには、それを `+layout.server.js` に移動し、`LayoutLoad` 型を `LayoutServerLoad` に変更します。 `+layout.js` と同様に、`+layout.server.js` では [page options](page-options) — `prerender`、`ssr`、`csr` をエクスポートすることができます。 ## +server ページと同様に、`+server.js` ファイルを使うことで (よく 'API ルート(API route)' または 'エンドポイント(endpoint)' とも呼ばれる) ルート(routes) を定義でき、これによってレスポンスを完全にコントロールすることができます。`+server.js` ファイル は `GET`、`POST`、`PATCH`、`PUT`、`DELETE`、`OPTIONS`、`HEAD` といった HTTP verbs に対応する関数をエクスポートします。これは [`RequestEvent`](@sveltejs-kit#RequestEvent) を引数に取り、[`Response`](https://developer.mozilla.org/ja/docs/Web/API/Response) オブジェクトを返します。 例えば、`GET` ハンドラを使用した `/api/random-number` ルート(route)を作成できます: ```js /// file: src/routes/api/random-number/+server.js import { error } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export function GET({ url }) { const min = Number(url.searchParams.get('min') ?? '0'); const max = Number(url.searchParams.get('max') ?? '1'); const d = max - min; if (isNaN(d) || d < 0) { error(400, 'min and max must be numbers, and min must be less than max'); } const random = min + Math.random() * d; return new Response(String(random)); } ``` `Response` の第一引数には [`ReadableStream`](https://developer.mozilla.org/ja/docs/Web/API/ReadableStream) を指定することができ、大量のデータをストリームしたり、server-sent events を作成したりすることができます (AWS Lambda のような、レスポンスをバッファするプラットフォームにデプロイする場合は除きます)。 便宜上、`@sveltejs/kit` の [`error`](@sveltejs-kit#error)、[`redirect`](@sveltejs-kit#redirect)、[`json`](@sveltejs-kit#json) メソッドを使用することは可能です (ただし、使用する必要はありません)。 エラーがスローされる場合 (`error(...)` の場合でも、予期せぬエラーの場合でもどちらでも)、レスポンスは `Accept` ヘッダーに応じて、そのエラーの JSON 表現か、`src/error.html` でカスタマイズすることができるフォールバックエラーページとなります。この場合、[`+error.svelte`](#error) コンポーネントはレンダリングされません。エラーハンドリングに関する詳細は [こちら](errors) からお読み頂けます。 > [!NOTE] `OPTIONS` ハンドラを作成する場合、Vite が `Access-Control-Allow-Origin` ヘッダーと `Access-Control-Allow-Methods` ヘッダーを注入することにご注意ください。本番環境では、あなたが明示的に追加しない限り注入されないはずです。 > [!NOTE] `+layout` files have no effect on `+server.js` files. If you want to run some logic before each request, add it to the server [`handle`](hooks#Server-hooks-handle) hook. ### Receiving data `+server.js` ファイルは、`POST`/`PUT`/`PATCH`/`DELETE`/`OPTIONS`/`HEAD` ハンドラをエクスポートすることで、完全な API を作成することができます: ```svelte + = {total} ``` ```js /// file: src/routes/api/add/+server.js import { json } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export async function POST({ request }) { const { a, b } = await request.json(); return json(a + b); } ``` > [!NOTE] 一般的には、ブラウザからサーバーにデータを送信する方法としては [form actions](form-actions) のほうがより良い方法です。 > [!NOTE] `GET` ハンドラがエクスポートされている場合、`HEAD` リクエストは `GET` ハンドラのレスポンスボディの `content-length` を返します。 ### Fallback method handler `fallback` ハンドラをエクスポートすると、ハンドリングされていないリクエスト (`+server.js` にそれ専用のエクスポートがない `MOVE` などのメソッドを含む) にマッチします。 ```js /// file: src/routes/api/add/+server.js import { json, text } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export async function POST({ request }) { const { a, b } = await request.json(); return json(a + b); } // This handler will respond to PUT, PATCH, DELETE, etc. /** @type {import('./$types').RequestHandler} */ export async function fallback({ request }) { return text(`I caught your ${request.method} request!`); } ``` > [!NOTE] `HEAD` リクエストの場合、`fallback` ハンドラより `GET` ハンドラが優先されます。 ### Content negotiation `+server.js` ファイルは `+page` ファイルと同じディレクトリに置くことができ、これによって同じルート(route)がページにも API エンドポイントにもなるようにすることができます。これがどちらなのか判断するために、SvelteKit は以下のルールを適用します: - `PUT`/`PATCH`/`DELETE`/`OPTIONS` リクエストは、ページには適用されないため、常に `+server.js` で処理されます。 - `GET`/`POST`/`HEAD` リクエストは、`accept` ヘッダーが `text/html` を優先している場合 (言い換えると、ブラウザのページリクエストの場合)、ページリクエストとして扱われます。それ以外の場合は `+server.js` で処理されます。 - `GET` リクエストに対するレスポンスには `Vary: Accept` ヘッダーが含まれるため、プロキシーやブラウザは HTML と JSON のレスポンスを別々にキャッシュします。 ## $types これまでの例を通してずっと、`$types.d.ts` ファイルからインポートしてきました。これは、TypeScript (または JavaScript を JSDoc の型アノテーションと) 使用している場合に最上位のファイル(root files)を扱う際に型の安全性をもたらすために SvelteKit が隠しディレクトリに作成するファイルです。 例えば、`let { data } = $props()` に `PageProps` (または `+layout.svelte` ファイルの場合は `LayoutProps`) アノテーションを付けると、`data` の型は `load` の戻り値であると TypeScript に伝えることができます: ```svelte ``` > [!NOTE] > The `PageProps` and `LayoutProps` types, added in 2.16.0, are a shortcut for typing the `data` prop as `PageData` or `LayoutData`, as well as other props, such as `form` for pages, or `children` for layouts. In earlier versions, you had to type these properties manually. For example, for a page: > > ```js > /// file: +page.svelte > /** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */ > let { data, form } = $props(); > ``` > > Or, for a layout: > > ```js > /// file: +layout.svelte > /** @type {{ data: import('./$types').LayoutData, children: Snippet }} */ > let { data, children } = $props(); > ``` `load` 関数に `PageLoad`、`PageServerLoad`、`LayoutLoad`、`LayoutServerLoad` (それぞれ `+page.js`、`+page.server.js`、`+layout.js`、`+layout.server.js`) というアノテーションを付けると、`params` と戻り値が正しく型付けされることが保証されます。 VS Code や、language server protocol と TypeScript plugin をサポートする IDE を使用している場合は、これらの型を _完全に_ 省略することができます! Svelte の IDE ツール類があなたのために正しい型を挿入してくれるので、あなたはご自身で型を書くことなく型チェックすることができます。これはコマンドラインツール `svelte-check` でも機能します。 `$types` の省略については、私たちの[ブログ記事](/blog/zero-config-type-safety)でより詳細な情報をお読み頂けます。 ## その他のファイル ルート(route)ディレクトリ内のその他のファイルは SvelteKit から無視されます。つまり、コンポーネントやユーティリティモジュールを、それらを必要とするルート(routes)に配置することができます。 コンポーネントやモジュールが複数のルート(routes)から必要な場合、[`$lib`]($lib) にそれらを配置すると良いでしょう。 ## その他の参考資料 - [Tutorial: Routing](/tutorial/kit/pages) - [Tutorial: API routes](/tutorial/kit/get-handlers) - [Docs: Advanced routing](advanced-routing)