Svelte入門:SvelteKitでのデータ読み込み -Vol.6-

スポンサーリンク
Svelte入門:SvelteKitでのデータ読み込み -Vol.6- ノウハウ
Svelte入門:SvelteKitでのデータ読み込み -Vol.6-
この記事は約6分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

今日は、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()関数の動作について:

  1. +page.server.js+layout.server.js内:
  • 親の+layout.server.jsファイルからデータを返す
  1. +page.js+layout.js内:
  • 親の+layout.jsファイルからデータを返す
  • ただし、+layout.jsが存在しない場合は({ data }) => data関数として扱われる
  • この場合、+layout.jsで「隠蔽」されていない親の+layout.server.jsのデータも返す
  1. パフォーマンスに関する注意:
  • 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でのデータ読み込みについて解説しました。

よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました