Svelte入門:SvelteKitでルーティング -Vol.4-

スポンサーリンク
Svelte入門:SvelteKitでルーティング -Vol.4- 用語解説
Svelte入門:SvelteKitでルーティング -Vol.4-
この記事は約7分で読めます。
よっしー
よっしー

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

今日は、ルーティングについて解説しています。

スポンサーリンク

背景

ルーティングについて調査する機会がありましたので、その時の内容を備忘として記事に残しました。

+server

SvelteKitというウェブアプリケーションフレームワークにおけるルーティングの機能について説明しています。主なポイントは以下の通りです:

  1. ページだけでなく、+server.jsファイルを使用してルートを定義することができます。
  • これは「APIルート」や「エンドポイント」とも呼ばれます。
  1. +server.jsファイルを使用すると、レスポンスを完全に制御できます。
  2. +server.jsファイルでは、HTTPメソッドに対応する関数をエクスポートします。
  • 対応するHTTPメソッドには、GET、POST、PATCH、PUT、DELETE、OPTIONS、HEADなどがあります。
  1. これらの関数は、RequestEvent引数を受け取り、Responseオブジェクトを返します。

この機能により、開発者はAPIエンドポイントやカスタムサーバーサイドの処理を柔軟に実装することができます。通常のページレンダリングとは異なり、この方法では生のHTTPリクエストとレスポンスを直接扱うことができるため、より高度な制御が可能になります。

たとえば、GET ハンドラーを使用して /api/random-number ルートを作成できます。

// src/routes/api/random-number/+server.js
import { error } from '@sveltejs/kit';

/** @type {import('./$types').RequestHandler} */
export function GET({ url }) {
	const min = Number(url.searchParams.get('min') ?? '0');
	const max = Number(url.searchParams.get('max') ?? '1');

	const d = max - min;

	if (isNaN(d) || d < 0) {
		error(400, 'min and max must be numbers, and min must be less than max');
	}

	const random = min + Math.random() * d;

	return new Response(String(random));
}
  1. Responseオブジェクトの生成:
  • Responseの最初の引数としてReadableStreamを使用できます。
  • これにより、大量のデータのストリーミングやサーバーセントイベントの作成が可能になります。
  • ただし、AWS Lambdaのようにレスポンスをバッファリングするプラットフォームにデプロイする場合は、この機能が制限される可能性があります。
  1. 便利なメソッド:
  • @sveltejs/kitから提供されるerrorredirectjsonメソッドを使用できます。
  • これらのメソッドは便利ですが、必須ではありません。
  1. エラー処理:
  • エラーが発生した場合(error(...)を使用した場合や予期せぬエラーの場合)、レスポンスはエラーのJSON表現またはフォールバックエラーページになります。
  • どちらになるかは、リクエストのAcceptヘッダーによって決まります。
  • フォールバックエラーページはsrc/error.htmlでカスタマイズできます。
  • この場合、+error.svelteコンポーネントは描画されません。

これらの機能により、開発者はより柔軟にサーバーサイドの処理を制御できます。大規模なデータ処理やリアルタイムの通信、エラー処理など、さまざまなシナリオに対応できるようになっています。

特に、ストリーミング機能は大量のデータを効率的に扱う場合に有用です。また、エラー処理の柔軟性も高く、APIとウェブページの両方に適した形でエラーレスポンスを返すことができます。

OPTIONS ハンドラーを作成するときは、Vite が Access-Control-Allow-Origin ヘッダーと Access-Control-Allow-Methods ヘッダーを挿入することに注意してください。これらは追加しない限り本番環境には存在しません。

Receiving data

POST/PUT/PATCH/DELETE/OPTIONS/HEAD ハンドラーをエクスポートすると、+server.js ファイルを使用して完全な API を作成できます。

// src/routes/add/+page.svelte
<script>
	let a = 0;
	let b = 0;
	let total = 0;

	async function add() {
		const response = await fetch('/api/add', {
			method: 'POST',
			body: JSON.stringify({ a, b }),
			headers: {
				'content-type': 'application/json'
			}
		});

		total = await response.json();
	}
</script>

<input type="number" bind:value={a}> +
<input type="number" bind:value={b}> =
{total}

<button on:click={add}>Calculate</button>
// src/routes/api/add/+server.js
import { json } from '@sveltejs/kit';

/** @type {import('./$types').RequestHandler} */
export async function POST({ request }) {
	const { a, b } = await request.json();
	return json(a + b);
}

一般に、ブラウザからサーバーにデータを送信するには、フォーム アクションの方が適しています。

GET ハンドラーがエクスポートされる場合、HEAD リクエストは GET ハンドラーの応答本文のコンテンツ長を返します。

Fallback method handler

フォールバック ハンドラーのエクスポートは、+server.js からの専用エクスポートを持たない MOVE などのメソッドを含む、未処理のリクエスト メソッドと一致します。

// src/routes/api/add/+server.js
import { json, text } from '@sveltejs/kit';

export async function POST({ request }) {
	const { a, b } = await request.json();
	return json(a + b);
}

// This handler will respond to PUT, PATCH, DELETE, etc.
/** @type {import('./$types').RequestHandler} */
export async function fallback({ request }) {
	return text(`I caught your ${request.method} request!`);
}

HEAD リクエストの場合、GET ハンドラーはフォールバック ハンドラーよりも優先されます。

Content negotiation

+server.js ファイルは +page ファイルと同じディレクトリに配置でき、同じルートをページまたは API エンドポイントにすることができます。どちらを決定するために、SvelteKit は次のルールを適用します。

  • PUT/PATCH/DELETE/OPTIONS リクエストはページには適用されないため、常に +server.js によって処理されます。
  • GET/POST/HEAD リクエストは、accept ヘッダーが text/html を優先する場合 (つまり、ブラウザ ページ リクエストである場合)、ページ リクエストとして扱われます。それ以外の場合は、+server.js によって処理されます。
  • GET リクエストへの応答には Vary: Accept ヘッダーが含まれるため、プロキシとブラウザは HTML 応答と JSON 応答を別々にキャッシュします。

おわりに 

今日は、 ルーティングについて解説しました。

よっしー
よっしー

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

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

コメント

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