こんにちは。よっしーです(^^)
今日は、SvelteKitでのデータ読み込みについて解説しています。
背景
SvelteKitでのデータ読み込みについて調査する機会がありましたので、その時の内容を備忘として記事に残しました。
SvelteKitでのデータ読み込み
+page.svelte コンポーネント (およびそれに含まれる +layout.svelte コンポーネント) をレンダリングする前に、多くの場合、データを取得する必要があります。これは、ロード関数を定義することによって行われます。
ヘッダー
サーバー ロード関数とユニバーサル ロード関数はどちらも setHeaders 関数にアクセスでき、サーバー上で実行されている場合は、応答のヘッダーを設定できます。(ブラウザーで実行されている場合、setHeaders は効果がありません。) これは、ページをキャッシュする場合に便利です。次に例を示します。
// src/routes/products/+page.js
/** @type {import('./$types').PageLoad} */
export async function load({ fetch, setHeaders }) {
const url = `https://cms.example.com/products.json`;
const response = await fetch(url);
// cache the page for the same length of time
// as the underlying data
setHeaders({
age: response.headers.get('age'),
'cache-control': response.headers.get('cache-control')
});
return response.json();
}
同じヘッダーを複数回設定すると (別個のロード関数内であっても) エラーになります。特定のヘッダーは 1 回しか設定できません。 setHeaders を使用して set-cookie ヘッダーを追加することはできません。代わりに cookies.set(name, value, options) を使用してください。
親データの使用
場合によっては、ロード関数が親ロード関数からのデータにアクセスすると便利な場合があります。これは awaitparent() で実行できます。
// src/routes/+layout.js
/** @type {import('./$types').LayoutLoad} */
export function load() {
return { a: 1 };
}
// src/routes/abc/+layout.js
/** @type {import('./$types').LayoutLoad} */
export async function load({ parent }) {
const { a } = await parent();
return { b: a + 1 };
}
// src/routes/abc/+page.js
/** @type {import('./$types').PageLoad} */
export async function load({ parent }) {
const { a, b } = await parent();
return { c: a + b };
}
// src/routes/abc/+page.svelte
<script>
/** @type {import('./$types').PageData} */
export let data;
</script>
<!-- renders `1 + 2 = 3` -->
<p>{data.a} + {data.b} = {data.c}</p>
+page.js の読み込み関数は、直接の親だけでなく、両方のレイアウト読み込み関数からマージされたデータを受け取ることに注意してください。
parent()
関数の動作について:
+page.server.js
と+layout.server.js
内:
- 親の
+layout.server.js
ファイルからデータを返す
+page.js
と+layout.js
内:
- 親の
+layout.js
ファイルからデータを返す - ただし、
+layout.js
が存在しない場合は({ data }) => data
関数として扱われる - この場合、
+layout.js
で「隠蔽」されていない親の+layout.server.js
のデータも返す
- パフォーマンスに関する注意:
await parent()
使用時にウォーターフォール(連鎖的な遅延)を避けること- 例:
getData(params)
がparent()
の結果に依存しない場合、レンダリングの遅延を避けるため先に呼び出すべき
この仕組みは、SvelteKitのレイアウトとページ構造におけるデータの流れとパフォーマンスの最適化に関係しています。
// +page.js
/** @type {import('./$types').PageLoad} */
export async function load({ params, parent }) {
const data = await getData(params);
const parentData = await parent();
return {
...data
meta: { ...parentData.meta, ...data.meta }
};
}
Errors
ロード中にエラーがスローされた場合は、最も近い +error.svelte がレンダリングされます。予期されるエラーの場合は、@sveltejs/kit のエラー ヘルパーを使用して、HTTP ステータス コードとオプションのメッセージを指定します。
// src/routes/admin/+layout.server.js
import { error } from '@sveltejs/kit';
/** @type {import('./$types').LayoutServerLoad} */
export function load({ locals }) {
if (!locals.user) {
error(401, 'not logged in');
}
if (!locals.user.isAdmin) {
error(403, 'not an admin');
}
}
error(…) を呼び出すと例外がスローされるため、ヘルパー関数内からの実行を簡単に停止できます。 予期しないエラーがスローされた場合、SvelteKit は handleError を呼び出し、それを 500 内部エラーとして処理します。
おわりに
今日は、 SvelteKitでのデータ読み込みについて解説しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント