こんにちは。よっしーです(^^)
今日は、SvelteKitでのデータ読み込みについて解説しています。
背景
SvelteKitでのデータ読み込みについて調査する機会がありましたので、その時の内容を備忘として記事に残しました。
SvelteKitでのデータ読み込み
+page.svelte コンポーネント (およびそれに含まれる +layout.svelte コンポーネント) をレンダリングする前に、多くの場合、データを取得する必要があります。これは、ロード関数を定義することによって行われます。
ユニバーサル vs サーバー
これまで見てきたように、ロード関数には 2 つの種類があります。
- page.js および layout.js ファイルは、サーバーとブラウザーの両方で実行されるユニバーサル ロード関数をエクスポートします。
- page.server.js および layout.server.js ファイルは、サーバー側でのみ実行されるサーバー ロード関数をエクスポートします。
概念的には同じものですが、知っておくべき重要な違いがいくつかあります。
どのロード関数はいつ実行されますか?
サーバーのload
関数は常にサーバー上で実行されます。
一方、ユニバーサルなload
関数は、デフォルトでは以下のように動作します:
- ユーザーが初めてページを訪れた時、SSR(サーバーサイドレンダリング)中にサーバーで実行されます。
- その後、ハイドレーション中に再度実行され、fetchリクエストの応答を再利用します。
- それ以降の呼び出しはすべてブラウザで行われます。
ただし、ページオプションでこの挙動をカスタマイズすることができます。サーバーサイドレンダリングを無効にすると、SPAとなり、ユニバーサルなload
関数は常にクライアント側で実行されます。
ルートにユニバーサルとサーバーの両方のload
関数が含まれている場合、サーバーのload
関数が先に実行されます。
load
関数は通常実行時に呼び出されますが、ページをプリレンダリングする場合はビルド時に呼び出されます。
入力
ユニバーサルとサーバーの両方のload
関数は、以下の共通のプロパティとファンクションにアクセスできます:
- リクエストを記述するプロパティ:
params
、route
、url
- 様々な機能:
fetch
、setHeaders
、parent
、depends
、untrack
サーバーのload
関数はServerLoadEvent
で呼び出され、これはRequestEvent
からclientAddress
、cookies
、locals
、platform
、request
を継承しています。
ユニバーサルのload
関数はLoadEvent
で呼び出され、これにはdata
プロパティがあります。+page.js
と+page.server.js
(または+layout.js
と+layout.server.js
)の両方にload
関数がある場合、サーバーのload
関数の戻り値がユニバーサルのload
関数の引数のdata
プロパティとなります。
出力
ユニバーサルのload
関数は、カスタムクラスやコンポーネントのコンストラクタを含む、任意の値を持つオブジェクトを返すことができます。
一方、サーバーのload
関数は、ネットワーク経由で転送できるように、devalueでシリアライズ可能なデータを返す必要があります。これには以下が含まれます:
- JSONで表現できるもの
BigInt
、Date
、Map
、Set
、RegExp
などの特殊なデータ型- 反復的または循環的な参照
また、サーバーのload
関数のデータにプロミスを含めることができ、その場合はブラウザにストリーミングされます。
いつどれを使うか
サーバーのload
関数の利点:
- データベースやファイルシステムから直接データにアクセスする必要がある場合に便利
- プライベートな環境変数を使用する必要がある場合に適している
ユニバーサルのload
関数の利点:
- 外部APIからデータを
fetch
する際、プライベートな認証情報が不要な場合に有用
(SvelteKitがサーバーを経由せず、直接APIからデータを取得できるため) - Svelteコンポーネントのコンストラクタなど、シリアライズできないものを返す必要がある場合に適している
稀に両方を組み合わせて使用する場合:
- 例:サーバーからのデータで初期化されたカスタムクラスのインスタンスを返す必要がある場合
- この場合、サーバーの
load
関数の戻り値は直接ページに渡されず、ユニバーサルのload
関数のdata
プロパティとして渡される
// src/routes/+page.server.js
/** @type {import('./$types').PageServerLoad} */
export async function load() {
return {
serverMessage: 'hello from server load function'
};
}
// src/routes/+page.js
/** @type {import('./$types').PageLoad} */
export async function load({ data }) {
return {
serverMessage: data.serverMessage,
universalMessage: 'hello from universal load function'
};
}
おわりに
今日は、 SvelteKitでのデータ読み込みについて解説しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント