load 関数の基本
SvelteKit には、+pages.ts
や +pages.server.ts
といった、特殊なルートファイルにデータのロード処理を定義する仕組みが用意されています。
ページコンポーネント (+page.svelte
) の UI 実装からデータのロード処理を分離することで、データの取得タイミングを細かく制御できるようになり、以下のような恩恵を得られます。
- サーバーサイドレンダリング (SSR)
- ビルド時に外部データを使ってページを生成することができます。 静的な HTML を配信することは、SEO の観点で有利に働く可能性があります。 外部 API の呼び出しにアクセストークンが必要な場合は、サーバーサイドでのみ呼び出すようにすることで、アクセストークンを公開せずに済みます。
- プリロード
- SvelteKit は、リンクホバーなどをトリガーにして、ページ遷移前にデータをプリロードすることができます。
- ロード処理の使い回し
layout.js(.ts
) やlayout.server.js(.ts)
にデータのロード処理を記述することで、そのレイアウトが適用される複数のページから同じデータを参照できます。
データのロード処理は、決められた名前のルートファイルで、load
という名前の関数を export
することで定義します(Promise
を返す async
関数として定義することも可能です)。
load
関数から return
した値は、ページコンポーネント内から data
という変数で参照することができます。
この対応付けは SvelteKit のルールであり、慣れるしかありません(逆にこの作法を知らないとコードを読めません)。
load
関数は、ユーザー操作によってインタラクティブに情報を取得するためのものというよりは、あくまでページの初期表示内容を取得するためのものだと考えるとよいです。
load
関数は、src/routes
ディレクトリ以下に配置する次のようなファイルに定義することができ、それぞれ呼び出されるタイミング(サーバーサイド (SSR) or クライアントサイド (CSR))や、適用範囲が異なっています。
ファイル名 | CSR | SSR | 注釈 | 適用範囲 |
---|---|---|---|---|
+page.js(.ts) | ✅ | ✅※ | ※ export const ssr = false と記述した場合はクライアントサイドでのみ呼び出されます。 | 同一ディレクトリの +page.svelte |
+page.server.js(.ts) | ─ | ✅ | サーバーからしかアクセスできない外部 API にアクセスする場合はこれを使います。 | 同一ディレクトリの +page.svelte |
+layout.js(.ts) | ✅ | ✅※ | export const ssr = false と記述した場合はクライアントサイドでのみ呼び出されます。 | +layout.svelte とそれが適用されるファイル |
+layout.server.js(.ts) | ─ | ✅ | サーバーからしかアクセスできない外部 API にアクセスする場合はこれを使います。 | +layout.svelte とそれが適用されるファイル |
基本的には、下記の方針でファイルを使い分ければよいです。
- 単一のページコンポーネント (
+page.svelte
) で使うdata
を提供するload
関数を実装したい- サーバーサイドだけで実行したい →
+page.server.js(.ts)
- クライアントサイドだけで実行したい →
+page.js(.ts)
+export const ssr = false
- 両サイドで実行しても OK なら →
+page.js(.ts)
- サーバーサイドだけで実行したい →
- レイアウト (
+layout.svelte
) とレイアウトの適用範囲で使うdata
を提供するload
関数を実装したい- サーバーサイドだけで実行したい →
+layout.server.js(.ts)
- クライアントサイドだけで実行したい →
+layout.js(.ts)
+export const ssr = false
- 両サイドで実行しても OK なら →
+layout.js(.ts)
- サーバーサイドだけで実行したい →
具体例
TypeScript を使って実装する場合の例をいくつか紹介します。
固定のデータを返す
まずは load()
関数で固定のデータを返す簡単な例です。
load
関数の返すオブジェクトの型情報が、data
変数の型情報に自動的に反映されます。
TypeScript の型情報としては、./$types
という SvelteKit の特殊パスでインポートできる PageLoad
と PageData
を使用します。
このレベルの load
関数実装にはほとんど意味はないですが、まずは基本的な使い方ということで。
ページのパス (URL) によって異なるデータを返す
src/routes/users/[name]/+pages.svelte
のような、動的ルートに対する load
関数を定義することもできます。
この場合、URL 内のプレースホルダー部分(この例では [name]
)に指定された値は、load
関数に渡される LoadEvent
オブジェクトを使って、event.params.name
のように参照することができます。
ページコンポーネントの実装は、前述のものと同じです。
これで、http://localhost:5173/users/maku
という URL でアクセスしたときに Hello, maku!
と表示されれば成功です。
外部データを fetch する
多くの場合、load
関数の中では外部のデータを読み込むことになると思います。
例えば、Web API で取得するデータや、サーバー上の JSON ファイルなどです。
このようなデータの取得は非同期処理 (async
) になるため、load
関数自体も async
関数として定義できるようになっています。
次の例では、load
関数から GitHub の REST API を呼び出しています。
load
関数の中では、load
関数に渡される fetch
関数を使用する ことに注意してください。
load
関数はいろいろなタイミングで呼び出されますが、この専用の fetch
関数を使うことで、SvelteKit がよい感じの振る舞いになるよう制御してくれます(参考: Making fetch requests)。
load 関数についての雑多メモ
ページアクセス時に 404 エラーを発生させる
SvelteKit が提供する error
関数を使って作成したオブジェクトを、load
関数から throw
することで、明示的に 404 エラーを発生させることができます。
次の例では、URL の [slug]
部分で特定のパス以外が指定されたときに 404 エラーを発生させています。
上記のように実装した場合、/blog/hello-world
にはアクセスできますが、それ以外の /blog/aaa
などにアクセスすると 404 エラーページが表示されます。