TL;DR
- Svelte 公式チュートリアルの Advanced SvelteKit。SvelteKit の Hooks、Page options、Link options、
loadの応用、環境変数を扱う。 - server load と universal load を両方定義すると、server load の戻り値はページに直接渡らず、universal load の
data引数に渡される。
内容
Hooks
Hook は SvelteKit のデフォルトの振る舞いに割り込んで上書きする仕組みで、src/hooks.server.js か src/hooks.client.js から export する。
handle はリクエストを受け取るたびに実行される。引数の event は RequestEvent で、cookies、fetch、locals、params、url などを持つ。event.fetch は受け取ったリクエストの cookie や authorization を引き継ぐので、サーバ上で認証付きのリクエストを送れる。もう 1 つの引数 resolve に event を渡すと通常のルーティングで処理され、transformPageChunk で生成された HTML を書き換えられる。
handleFetch はサーバで SvelteKit の fetch が呼ばれたときに、handleError は予期せぬエラーが起きたときに実行される。
Page options
SvelteKit はデフォルトで SSR と CSR を組み合わせて動く。初回アクセス時は SSR した HTML と最低限の JavaScript を送ってハイドレーションし、その後のページ遷移は CSR で処理する。
この動作は +page.js や +layout.js から Page options を export して変える。export const prerender = true でプリレンダリング(SSG)できるが、どのユーザもサーバから同じ内容を受け取り、Form actions を含まないことが条件になる。動的なルートパラメータを持つページは、prerender.entries で指定するか、指定したページからリンクをたどって到達できればプリレンダリングできる。
末尾のスラッシュは SEO やプリレンダリングの保存先に影響するので、SvelteKit はデフォルトで削除する。trailingSlash を export するとこの挙動を変えられる。
Link options
Link options の data-sveltekit-preload-data を付けると、デスクトップではホバー時、モバイルではタップ時にナビゲーションを始める。デフォルトのテンプレートでは <body> に付いている。データを読まずに JavaScript だけを先読みするには data-sveltekit-preload-code を使う。ページをリロードして遷移させたいときは data-sveltekit-reload を付ける。
Advanced loading
外部 API から直接データを取りたいときや、コンポーネントのようにシリアライズできないものを返したいときは、+page.server.js ではなく +page.js で load を export する。サーバ側の load を server load、+page.js の load を universal load と呼ぶ。
両方を使用する場合は、server load の戻り値は直接ページには渡されず、universal load 関数に (data プロパティとして) 渡されます
親の load のデータは await parent() で取る。universal load は親の server load からも取れるが、server load は親の server load からしか取れない。
ページを移動すると、SvelteKit は変更があった load だけを呼び直す。load の中で fetch(url) を呼ぶとその URL が依存関係として登録され、invalidate(url) でその load を再実行できる。depends('data:now') で手動でも登録できる。invalidateAll は URL の依存を持たない load も再実行するので、invalidate(() => true) とは同じではない。
Environment variables
$env/static/private と $env/dynamic/private は、+page.server.js などのサーバ用のモジュールと src/lib/server 以下でしか import できない。
キーワード
自分の理解
+page.svelte や +layout.svelte では、親の load が返したものすべてに Props からアクセスできる。これと「universal load の戻り値だけが渡される」という話を合わせると、混乱する。SvelteKit の load 関数を図解した記事の図が分かりやすかった。実際に試した結果は+page.js と +page.server.js が両方存在するページでリロードすると、+page.server.js の load 関数は 2 回呼び出されるにまとめた。