こんにちは。よっしーです(^^)
今日は、SvelteKitでのルーティングについて解説しています。
背景
SvelteKitでのルーティングについて調査する機会がありましたので、その時の内容を備忘として記事に残しました。
マッチング
src/routes/fruits/[page]
のようなルートは、/fruits/apple
にマッチしますが、/fruits/rocketship
にもマッチしてしまいます。これは望ましくありません。ルートパラメータが適切な形式であることを確認するために、マッチャーを追加できます。マッチャーはパラメータ文字列("apple"
や"rocketship"
)を受け取り、それが有効な場合はtrue
を返します。これをparams
ディレクトリに追加します…
src/params/fruit.js
/**
* @param {string} param
* @return {param is ('apple' | 'orange')}
* @satisfies {import('@sveltejs/kit').ParamMatcher}
*/
export function match(param) {
return param === 'apple' || param === 'orange';
}
…そして、ルートを拡張します:
src/routes/fruits/[page]
src/routes/fruits/[page=fruit]
パス名がマッチしない場合、SvelteKitは他のルート(以下で指定されているソート順を使用)とのマッチを試み、最終的に404を返します。
params
ディレクトリ内の各モジュールはマッチャーに対応しています。ただし、*.test.js
と*.spec.js
ファイルは例外で、これらはマッチャーの単体テストに使用できます。
マッチャーはサーバー側とブラウザの両方で実行されます。
この機能を使用することで、より精密なルーティング制御が可能になります。特定のパラメータ値のみを許可したり、複雑な条件に基づいてルートをマッチングしたりすることができます。これにより、アプリケーションのセキュリティと予測可能性が向上します。
並べ替え
複数のルートが特定のパスにマッチする可能性があります。例えば、以下のルートはすべて /foo-abc
にマッチします:
src/routes/[...catchall]/+page.svelte
src/routes/[[a=x]]/+page.svelte
src/routes/[b]/+page.svelte
src/routes/foo-[c]/+page.svelte
src/routes/foo-abc/+page.svelte
SvelteKitは、どのルートがリクエストされているかを知る必要があります。そのために、以下のルールに従ってソートを行います…
- より具体的なルートが高優先度となります(例:パラメータのないルートは、1つの動的パラメータを持つルートよりも具体的で、優先度が高くなります)
- マッチャー付きのパラメータ(
[name=type]
)は、マッチャーなしのパラメータ([name]
)よりも優先度が高くなります [[optional]]
と[...rest]
パラメータは、ルートの最後の部分でない限り無視されます。最後の部分である場合、最低優先度として扱われます。つまり、ソーティングの目的ではx/[[y]]/z
はx/z
と同等に扱われます- 同点の場合はアルファベット順で解決されます
…これにより、以下の順序になります。つまり、/foo-abc
はsrc/routes/foo-abc/+page.svelte
を呼び出し、/foo-def
は他のより具体的でないルートではなくsrc/routes/foo-[c]/+page.svelte
を呼び出します:
src/routes/foo-abc/+page.svelte
src/routes/foo-[c]/+page.svelte
src/routes/[[a=x]]/+page.svelte
src/routes/[b]/+page.svelte
src/routes/[...catchall]/+page.svelte
このソーティングメカニズムにより、SvelteKitは最も適切なルートを選択できます。これは、複雑なルーティング構造を持つアプリケーションで特に重要です。開発者は、このソーティングルールを理解することで、意図したとおりにルートが解決されるようにルート構造を設計できます。
エンコーディング
いくつかの文字はファイルシステムで使用できません — LinuxとMacでは /
、Windowsでは \ / : * ? " < > |
です。#
と %
文字はURLで特別な意味を持ち、[ ] ( )
文字はSvelteKitで特別な意味を持つため、これらもルートの一部として直接使用することはできません。
これらの文字をルートで使用するには、16進数のエスケープシーケンスを使用できます。形式は [x+nn]
で、nn
は16進数の文字コードです:
\
—[x+5c]
/
—[x+2f]
:
—[x+3a]
*
—[x+2a]
?
—[x+3f]
"
—[x+22]
<
—[x+3c]
>
—[x+3e]
|
—[x+7c]
#
—[x+23]
%
—[x+25]
[
—[x+5b]
]
—[x+5d]
(
—[x+28]
)
—[x+29]
例えば、/smileys/:-)
ルートを作成するには、src/routes/smileys/[x+3a]-[x+29]/+page.svelte
ファイルを作成します。
JavaScriptを使用して文字の16進数コードを確認できます:
':'.charCodeAt(0).toString(16); // '3a'、したがって '[x+3a]'
Unicodeエスケープシーケンスも使用できます。通常は直接エンコードされていない文字を使用できるため必要ありませんが、何らかの理由で絵文字を含むファイル名を使用できない場合などに、エスケープされた文字を使用できます。つまり、以下は同等です:
src/routes/[u+d83e][u+dd2a]/+page.svelte
src/routes/🤪/+page.svelte
Unicodeエスケープシーケンスの形式は [u+nnnn]
で、nnnn
は 0000
から 10ffff
までの有効な値です。(JavaScriptの文字列エスケープとは異なり、ffff
を超えるコードポイントを表すためにサロゲートペアを使用する必要はありません。)Unicodeエンコーディングについて詳しく知りたい場合は、Programming with Unicodeを参照してください。
TypeScriptは先頭が .
の文字のディレクトリを扱うのに苦労するため、.well-known
ルートなどを作成する際にこれらの文字をエンコードすると便利かもしれません:src/routes/[x+2e]well-known/...
このエンコーディングシステムにより、通常は使用できない特殊文字や絵文字などをルートに含めることができます。これにより、より柔軟でユーザーフレンドリーなURL構造を作成できます。
おわりに
今日は、 SvelteKitでのルーティングについて解説しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント