ルーティング
Edit this page on GitHubSveltekitの核心は、 ファイルシステムベースのルーター です。これは、アプリケーション構造がコードベースの構造(具体的には src/routes
のコンテンツ)によって定義されることを意味します。
プロジェクトのコンフィグ を編集することで、これを異なるディレクトリに変更できます。
ルートには、ページ(pages) と エンドポイント(endpoints) の2つのタイプがあります。
ページは通常、ユーザーに表示するHTML(及びページに必要なCSSやJavaScript)を生成します。デフォルトでは、ページはクライアントとサーバーの両方でレンダリングされますが、この動作は設定によって変更可能です。
エンドポイントは、サーバー上でのみ実行されます(もしくはサイトをビルドするときにプリレンダリングしている場合)。これは、プライベートな認証情報を必要とするデータベースやAPIにアクセスする場合や、本番環境ネットワーク上のマシンにあるデータを返す場合などに使用されます。ページはエンドポイントにデータをリクエストすることができます。エンドポイントはデフォルトではJSONを返しますが、他のフォーマットでもデータを返すことができます。
ページ(Pages)permalink
ページ(Pages)は .svelte
ファイル (またはconfig.extensions
に記載されている拡張子のファイル) に書かれているSvelteコンポーネントです。デフォルトでは、ユーザーが初めてアプリにアクセスすると、サーバーレンダリングバージョンのページと、そのページを'ハイドレート(hydrate)'しクライアントサイドルーターを初期化するJavaScriptが提供されます。それ以降、他のページへのナビゲーションは全てクライアント側で処理され、ページの共通部分を再レンダリングする必要がなくなるため、高速でアプリのような操作感になります。
ファイル名でルート(route)が決まります。例えば、src/routes/index.svelte
はサイトのルート(root)になります。
src/routes/index.svelte
<svelte:head>
<title>Welcome</title>
</svelte:head>
<h1>Hello and welcome to my site!</h1>
<a href="/about">About my site</a>
src/routes/about.svelte
と src/routes/about/index.svelte
はどちらも /about
ルート(route)になります。
src/routes/about.svelte
<svelte:head>
<title>About</title>
</svelte:head>
<h1>About this site</h1>
<p>TODO...</p>
<a href="/">Home</a>
SvelteKit ではルート(routes)間のナビゲートに、フレームワーク固有の
<Link>
コンポーネントではなく、<a>
要素を使用します。
動的なパラメータは [カッコ]
を使用してエンコードされます。例えば、ブログ記事の場合は src/routes/blog/[slug].svelte
のように定義することがあるでしょう。これらのパラメータは、load
関数の中からアクセスできますし、page
ストアを使用してアクセスすることもできます。
ルート(route)は動的なパラメータを複数持つことができます。例えば、src/routes/[category]/[item].svelte
や src/routes/[category]-[item].svelte
といった具合です。(パラメータは 'non-greedy' です; x-y-z
のような曖昧なケースの場合、category
は x
、item
は y-z
になります。)
エンドポイント(Endpoints)permalink
エンドポイント(Endpoints)は .js
(または .ts
) ファイルに記述されるモジュールで、HTTP メソッドに対応する request handler 関数をエクスポートします。サーバー上でのみ利用可能なデータ(例えば、データベースやファイルシステムにあるデータ) を読み書きできるようにするという役割があります。
src/routes/items/[id].js
ts
importdb from '$lib/database';export async functionget ({params }) {// `params.id` comes from [id].jsconstitem = awaitdb .get (params .id );if (item ) {return {body : {item }};}return {status : 404};}
$lib
のインポートについては心配無用です、それについては後ほど触れます。
上記の get
関数の型は、SvelteKit が (outDir
の中に、rootDirs
オプションを使用して) 生成する ./[id].d.ts
ファイルにあり、params
にアクセスするときの型安全性を提供します。詳細は generated types をご覧ください。
この request handler の役割は、レスポンスを表す { status, headers, body }
オブジェクトを返すことです。status
は HTTPステータスコードです。
2xx
— 成功レスポンス (デフォルトは200
)3xx
— リダイレクション (location
ヘッダーが必要です)4xx
— クライアントエラー5xx
— サーバーエラー
ページエンドポイント(Page endpoints)permalink
エンドポイントとページのファイル名が(拡張子以外)同一である場合、そのページはその同名のファイルを持つエンドポイントからプロパティ(props)を取得します (クライアントサイドナビゲーションの時は fetch
が使用され、SSRの時には直接その関数を呼び出します)。
src/routes/items/[id].svelte
というページの場合は、上記のエンドポイント(src/routes/items/[id].js
)の body
からプロパティを取得します:
src/routes/items/[id].svelte
<script>
// エンドポイント(endpoint)からデータが取得される export let item;
</script>
<h1>{item.title}</h1>
ページとエンドポイントが同じURLになるため、ページから HTML を取得するのではなくエンドポイントから JSON を取得するときは accept: application/json
ヘッダーを付ける必要があります。また、URL に /__data.json
を追加することで(例: /items/[id]/__data.json
)、生データ(raw data)を取得できます。
スタンドアロンエンドポイント(Standalone endpoints)permalink
通常、エンドポイントはペアとなるページにデータを提供するために置きます。しかし、ページとは独立して置くこともできます。スタンドアロンエンドポイント(Standalone endpoints)は、返す body
の型について少し柔軟で、オブジェクトに加えて、Uint8Array
を返すこともできます。
スタンドアロンエンドポイントには必要に応じてファイル拡張子を付けることができますし、付けなければ直接アクセスすることができます:
ファイル名 | エンドポイント |
---|---|
src/routes/data/index.json.js | /data.json |
src/routes/data.json.js | /data.json |
src/routes/data/index.js | /data |
src/routes/data.js | /data |
streaming request body、response body については今後サポートされる予定です。
POST, PUT, PATCH, DELETEpermalink
エンドポイント(Endpoints)は、HTTP メソッドに対応する関数をエクスポートすることで、GET
だけでなく任意の HTTP メソッドを扱うことができます:
ts
export functionpost (event ) {...}export functionput (event ) {...}export functionpatch (event ) {...}export functiondel (event ) {...} // `delete` は予約語
get
と同様、これらの関数は body
を返すことができ、それをページにプロパティとして渡されます。get
からの 4xx/5xx レスポンスはエラーページのレンダリングとなりますが、GET 以外のリクエストに対する同様のレスポンスはそうならないので、フォームのバリデーションエラーのレンダリングのようなことを行うことができます:
src/routes/items.js
ts
import * asdb from '$lib/database';export async functionget () {constitems = awaitdb .list ();return {body : {items }};}export async functionpost ({request }) {const [errors ,item ] = awaitdb .create (request );if (errors ) {// バリデーションエラーを返しますreturn {status : 400,body : {errors }};}// 新たに作成された item にリダイレクトしますreturn {status : 303,headers : {location : `/items/${item .id }`}};}
src/routes/items.svelte
<script>
// このページでは常に `get` で取得したプロパティにアクセスします… export let items;
// …それに加えて、POST リクエストに応答してページがレンダリングされるときに // `post` からプロパティを取得します // 例えば、以下のようなフォームを送信したあとです export let errors;
</script>
{#each items as item}
<Preview item={item}/>
{/each}
<form method="post">
<input name="title">
{#if errors?.title}
<p class="error">{errors.title}</p>
{/if}
<button type="submit">Create item</button>
</form>
Body parsingpermalink
request
オブジェクトは標準の Request クラスのインスタンスです。そのため、簡単に request の body にアクセスできます:
ts
export async functionpost ({request }) {constdata = awaitrequest .formData (); // or .json(), or .text(), etcawaitcreate (data );return {status : 201 };}
Setting cookiespermalink
エンドポイント(Endpoints) は set-cookie
を含む headers
オブジェクトを返すことで、Cookie を設定することができます。複数の Cookie を同時に設定するには、配列を返します:
ts
export functionget () {return {headers : {'set-cookie': [cookie1 ,cookie2 ]}};}
HTTP method overridespermalink
HTML <form>
要素は、ネイティブでは GET
と POST
メソッドのみをサポートしています。例えば PUT
や DELETE
などのその他のメソッドを許可するには、それを configuration で指定し、_method=VERB
パラメータ (パラメータ名は設定で変更できます) を form の action
に追加してください:
svelte.config.js
ts
constconfig = {kit : {methodOverride : {allowed : ['PUT', 'PATCH', 'DELETE']}}};export defaultconfig ;
<form method="post" action="/todos/{id}?_method=PUT">
<!-- form elements --></form>
ネイティブの
<form>
の挙動を利用することで、JavaScript が失敗したり無効になっている場合でもアプリが動作し続けられます。
プライベートモジュールpermalink
名前が _
や .
で始まるファイルやディレクトリ(.well-known
は除く) はデフォルトでプライベートで、ルート(routes)を作成しません(ルートを作成するファイルからインポートすることは可能です)。どのモジュールをパブリックまたはプライベートとみなすかについては ルート(routes)
設定で設定することができます。
高度なルーティングpermalink
Restパラメータpermalink
ルート(route) セグメントの数がわからない場合は、rest 構文を使用することができます。例えば GitHub のファイルビューアのようなものを実装する場合には…
/[org]/[repo]/tree/[branch]/[...file]
…この場合、/sveltejs/kit/tree/master/documentation/docs/01-routing.md
をリクエストすると、以下のパラメータをページで使うことができます。
ts
{org: 'sveltejs',repo : 'kit',branch : 'master',file : 'documentation/docs/01-routing.md'}
src/routes/a/[...rest]/z.svelte
は/a/z
(つまり、パラメータがない場合) にマッチしますし、/a/b/z
や/a/b/c/z
などにもマッチします。rest パラメータの値が有効であることを、例えば matcher などを使用して、確実にチェックしてください。
Matchingpermalink
src/routes/archive/[page]
のようなルート(route)は /archive/3
にマッチしますが、/archive/potato
にもマッチしてしまいます。これを防ぎたい場合、パラメータ文字列("3"
や "potato"
)を引数に取ってそれが有効なら true
を返す matcher を params
ディレクトリに追加することで、ルート(route)のパラメータを適切に定義することができます…
src/params/integer.js
ts
export functionmatch (param ) {return /^\d+$/.test (param );}
…そしてルート(routes)を拡張します:
src/routes/archive/[page]
src/routes/archive/[page=integer]
もしパス名がマッチしない場合、SvelteKit は (後述のソート順の指定に従って) 他のルートでマッチするか試行し、どれにもマッチしない場合は最終的に 404 を返します。
Matcher は サーバーとブラウザの両方で動作します。
ソートpermalink
あるパスに対し、マッチするルート(routes)は複数でも構いません。例えば、これらのルート(routes)はどれも /foo-abc
にマッチします:
src/routes/[...catchall].svelte
src/routes/[a].js
src/routes/[b].svelte
src/routes/foo-[c].svelte
SvelteKit は、どのルート(route)に対してリクエストされているのかを判断しなければなりません。そのため、以下のルールに従ってこれらをソートします…
- より詳細・明確(specific)なルート(routes)ほど、より優先度が高い
- Standalone endpoints は、同じ詳細度(specificity)のページよりも優先度が高い
- matchers 付きのパラメータ (
[name=type]
) は matchers なしのパラメータ ([name]
) よりも優先度が高い - Restパラメータは最も優先度が低い
- 優先度が同じ場合はアルファベット順で解決される
…この順序で並べると、/foo-abc
の場合は src/routes/foo-[bar].svelte
を呼び出すことになります:
src/routes/foo-[c].svelte
src/routes/[a].js
src/routes/[b].svelte
src/routes/[...catchall].svelte