Svelte 公式チュートリアル Part 4: Advanced SvelteKit をやっていく
このスクラップについて
このスクラップでは Svelte 公式チュートリアル Part 4: Advanced SvelteKit を手を動かして学んでいく過程を記録する。
前のスクラップ
11/16 (木) はここから
今日は 20 分くらい学んでいこう。
Part 4 / Hooks / handle
export async function handle({ event, resolve }) {
if (event.url.pathname === '/ping') {
return new Response('pong');
}
return await resolve(event, {
transformPageChunk: ({ html }) => html.replace(
'<body',
'<body style="color: hotpink"'
)
});
}
フックとは SvelteKit のデフォルト動作を上書きする機能のこと。
最も基本的なフックは handle であり、src/hooks.server.js を作成して handle() 関数をエクスポートすることで作成できる。
handle() 関数の第 1 引数としてオプションを受け取り、オプションには event や resolve が含まれる。
event にはアクセスされたページの URL などが含まれる。
resolve はルートの +page.server.js や +page.svelte の実行結果の Promise を返す関数であり、第 2 引数のオプションで transformPageChunk を指定することで HTML の書き換えなどができる。
handle() 関数は Response オブジェクトを返せば良いので必ずしも resolve() を呼び出す必要はない。
Part 4 / Hooks / The RequestEvent object
export async function handle({ event, resolve }) {
event.locals.answer = 42;
return await resolve(event);
}
export function load(event) {
return {
message: `the answer is ${event.locals.answer}`
};
}
handle() 関数に渡される event オブジェクトは API routes やフォームアクション、ページの load() 関数に渡されるものと同じ。
RequestEvent のドキュメントにあるように様々なプロパティが含まれている、特に fetch() 関数が含まれているのが興味深い。
locals はアプリで使用するデータを格納するのに適している。
11/16 (木) はここまで
20 分経過したので累計時間は 20 分、次は下記から始める。
11/17 (金) はここから
今日も 20 分くらい学んでいこう。
Part 4 / Hooks / handleFetch
export async function handleFetch({ event, request, fetch }) {
const url = new URL(request.url);
if (url.pathname === '/a') {
return await fetch('/b');
}
return await fetch(request);
}
event オブジェクトには fetch() 関数が含まれている。
この fetch() 関数は拡張されており、cookie や authorization ヘッダーの引き継ぎや相対リクエストが可能。
API route などで fetch() 関数を呼び出した場合は HTTP リクエストは行われず、直接 GET() 関数などが呼ばれる。
handleFetch() フックは fetch() 関数の動作をカスタマイズするために使用される。
Part 4 / Hooks / handleError
export function handleError({ event, error }) {
console.error(error.stack);
return {
message: 'everything is fine',
code: 'JEREMYBEARIMY'
};
}
<script>
import { page } from '$app/stores';
</script>
<h1>{$page.status}</h1>
<p>{$page.error.message}</p>
<p>error code: {$page.error.code}</p>
handleError() フックは予期しないエラーが発生した時の動作をカスタマイズできる。
デフォルトの動作はコンソール出力だが例えば Slack などに通知することも可能。
handleError() 関数の戻り値は +error.svelte ページで page ストアを使って参照できる。
11/17 (金) はここまで
20 分経過したので累計時間は 40 分、次は下記から始める。
11/20 (月) はここから
今日は 10 分くらい学んでいこう。
Part 4 / Page options / Basic
+page.js や + page.server.js、+layout.js や +layout.server.js では ssr や csr などのページオプションをエクスポートすることで設定できる。
レイアウトの設定はすべての子孫に反映され、子孫のページやレイアウトは設定を上書きできる。
ルートレイアウトでデフォルトの設定をしておき、個々のページやレイアウトで設定を変更するのがメジャーな使い方になる。
Part 4 / Page options / ssr
export const ssr = false;
SvelteKit では SSR がデフォルトになっている。
コンポーネントによってはサーバー側でレンダリングできないものもある。
一例として window オブジェクトに即座にアクセスするコンポーネントが考えられる。
SSR を CSR に切り替えるには +page.server.js で export const ssr = false;
と書く。
11/20 (月) はここまで
10 分経過したので累計時間は 50 分、次は下記から始める。
11/21 (火) はここから
今日も 2 ページくらいやっていこう。
Part 4 / Page options / csr
export const csr = false;
csr を OFF にすることで JavaScript を実行しないようにできる。
おそらくデフォルトでは ON になっている。
Part 4 / Page options / prerender
export const prerender = true;
事前レンダリングとはリクエストの度ではなくビルド時に 1 回だけレンダリングすることを意味する。
事前レンダリングはサーバー負荷や表示速度の面でメリットがある。
一方、ビルド時間が長くなることや更新に再ビルドと再デプロイが必要になることがデメリット。
事前レンダリングはすべてのページで有効化できない。
すべてのリクエストに対して同じページ内容を返し、かつフォームアクションを使っていないページだけが事前レンダリングできる。
ルートパラメーターを使っているページでも事前レンダリングを有効化できる。
その場合は prerender.entries の設定を行う必要がある。
Part 4 / Page options / trailingSlash
export const trailingSlash = 'always';
export const trailingSlash = 'ignore';
trailing slash とは URL 末尾のスラッシュ(/)のこと。
SvelteKit では trailing slash はデフォルトで削除されるようになっている。
逆に trailing slash を付加したい場合は export const trailingSlash = 'always';
を実行する。
trailing slash の削除を無効化したい場合は export const trailingSlash = 'ignore';
を実行する。
11/21 (火) はここまで
20 分経過したので累計時間は 70 分、次は下記から始める。
11/22 (水) はここから
今日も軽くやっていこう。
Part 4 / Link options / Preloading
<nav>
<a href="/">home</a>
<a href="/slow-a" data-sveltekit-preload-data>slow-a</a>
<a href="/slow-b">slow-b</a>
</nav>
a タグに data-sveltekit-preload-data 属性を設けることでホバー/タップ時に事前読み込みができるので表示が速くなる。
この属性は個々の a タグに付与することもできるが body などに付与することで全てのリンクに設定を反映できる。
data-sveltekit-preload-data は指定がなければ hover になるが、tap や off も指定できる。
data-sveltekit-preload-data の代わりに data-sveltekit-preload-code を使うことで JavaScript コードのみを読み込むこともできる。
$app/navigation から preloadCode() や preloadData() 関数をインポートして script タグ内で事前読み込みを行うこともできる。
Part 4 / Link options / Reloading the page
<nav data-sveltekit-reload>
<a href="/">home</a>
<a href="/about">about</a>
</nav>
SvelteKit ではページ間のナビゲーションはページの再読み込みなしで行われる。
a タグやそのコンテナに data-sveltekit-reload 属性を付与することでページの再読み込みを行うように設定できる。
この他にもいくつかのリンクオプションがある。
- data-sveltekit-replacestate:ページ履歴を追加するのではなく書き換える。
- data-sveltekit-keepfocus:フォーカスを維持したままにする、検索ページなどで便利。
- data-sveltekit-noscroll:ページ内リンクをクリックした時にスクロールしないようにする。
11/22 (水) はここまで
20 分経過したので累計時間は 90 分、次は下記から始める。
11/23 (木) はここから
今日も 1〜2 ページやっていこう。
Part 4 / Advanced routing / Optional parameters
const greetings = {
en: 'hello!',
de: 'hallo!',
fr: 'bonjour!'
};
export function load({ params }) {
return {
greeting: greetings[params.lang ?? 'en']
};
}
ディレクトリ名を [param]
ではなく [[param]]
とすることでパスパラメーターを省略可能にできる。
省略可能にしたことで +page.svelte と [[param]]/+page.svelte が衝突してしまうので、その場合は +page.svelte の方を削除する。
Part 4 / Advanced routing / Rest parameters
ディレクトリ名を [path]
の代わりに [...path]
とすることで複数のパスセグメントにマッチできる。
[...path] ディレクトリと同じ階層に他のディレクトリが存在しても問題ない。
その場合は他のディレクトリへのマッチが優先され、いずれにもマッチしない場合に [...path] ディレクトリにマッチするようになる。
レストパラメーターは末尾にある必要はなく /items/[...path]/edit
や /items/[...path].json
にすることも可能。
11/23 (木) はここまで
15 分経過したので累計時間は 105 分、次は下記から始める。
11/28 (火) はここから
久々になってしまったが今日も 1〜2 ページやっていこう。
Part 4 / Advanced routing / Param matchers
export function match(value) {
return /^[0-9a-f]{6}$/.test(value);
}
パスパラメーターを正規表現などでチェックしたい場合には param matchers を利用できる。
param matchers を利用するには src/params に .js / .ts ファイルを作成し、match() 関数をエクスポートする。
どの param matchers を使用する場合はディレクトリ名を例えば [param=hex]
のようにする。
Part 4 / Advanced routing / Route groups
import { redirect } from '@sveltejs/kit';
export function load({ cookies, url }) {
if (!cookies.get('logged_in')) {
throw redirect(303, `/login?redirectTo=${url.pathname}`);
}
}
<slot />
<form method="POST" action="/logout">
<button>log out</button>
</form>
レイアウトを変更せずに共通のアプリケーションロジックを適用したい場合は route groups を利用できる。
典型的な例としてはユーザー認証が挙げられる。
route groups を利用するには (authed)
のような丸カッコでくくった名前でディレクトリを作成し、共通のアプリケーションロジックを適用したいディレクトリを移動する。
Part 4 / Advanced routing / Breaking out layouts
レイアウトをリセットするには +page@b.svelte
のようにファイル名に @ を入れる。
a/b/c/+page@b.svelte
は c のレイアウトではなく b のレイアウトが使われる。
ルートレイアウトにリセットするには +page@.svelte
のように書く。
ルートレイアウトはリセットすることができない。
11/28 (火) はここまで
25 分経過したので累計時間は 130 分、次は下記から始める。
11/29 (水) はここから
今日も 20 分くらいやっていこう。
Part 4 / Advanced loading / Universal load functions
<script>
import { page } from '$app/stores';
</script>
<nav
class:has-color={!!$page.data.color}
style:background={$page.data.color ?? 'var(--bg-2)'}
>
<a href="/">home</a>
<a href="/red">red</a>
<a href="/green">green</a>
<a href="/blue">blue</a>
{#if $page.data.component}
<svelte:component this={$page.data.component} />
{/if}
</nav>
<slot />
<style>
nav.has-color,
nav.has-color a {
color: white;
}
</style>
+page.js や +layout.js は universal load functions と呼ばれ、サーバーとクライアントの両方で実行される。
server load functions ではシリアライズできなくてサーバーからクライアントに渡せないものを渡すのに便利。
universal load functions はページロード時はサーバーとクライアントの両方で実行される。
それ以降はクライアントのみで実行される。
Part 4 / Advanced loading / Using both load functions
export async function load({ data }) {
const module = data.cool
? await import('./CoolComponent.svelte')
: await import('./BoringComponent.svelte');
return {
component: module.default,
message: data.message
};
}
server load functions と universal load functions は併用できる。
server の方が最初に実行され、universal の方が後に実行される。
universal の方から data 引数を通じて server の戻り値にアクセスできる。
戻り値はマージされないので、universal の方で明示的にリターンする必要がある。
11/29 (水) はここまで
20 分経過したので累計時間は 150 分、次は下記から始める。
11/30 (木) はここから
今日は 1 ページくらいやっていこう。
Part 4 / Advanced loading / Using parent data
export async function load() {
return { a: 1 };
}
export async function load({ parent }) {
const { a } = await parent();
return { b: a + 1 };
}
export async function load({ parent }) {
const { a, b } = await parent();
return { c: a + b };
}
load() 関数では parent() 関数を実行することでレイアウトの load() 関数の実行結果の Promise を取得することができる。
universal load functions は server と universal の両方のロード関数の実行結果を取得できる。
server load functions は server のロード関数の実行結果しか取得できない。
parent() を await する前にデータベースや API からデータを取得できる場合はそうした方が並列実行できるのでなるべく parent() は後から実行する方が良さそうだ。
Part 4 / Advanced loading / Invalidation
<script>
import { onMount } from 'svelte';
import { invalidate } from '$app/navigation';
export let data;
onMount(() => {
const interval = setInterval(() => {
invalidate('/api/now');
}, 1000);
return () => {
clearInterval(interval);
};
});
</script>
<h1>
{new Intl.DateTimeFormat([], {
timeStyle: 'full',
timeZone: data.timezone
}).format(new Date(data.now))}
</h1>
SvelteKit は何か入力が変化したと思われる時だけロード関数を再実行する。
何も変化していないにも関わらずロード関数を実行したい場合は invalidate() 関数を実行する必要がある。
invalidate() 関数には文字列だけではなく関数を引数として与えることができる。
11/30 (木) はここまで
20 分経過したので累計時間は 170 分、次は下記から始める。
12/1 (金) はここから
今日も 20 分くらいやっていこう。
もう 12 月か。
Part 4 / Advanced loading / Custom dependencies
export async function load({ depends }) {
depends('data:now');
return {
now: Date.now()
};
}
<script>
import { onMount } from 'svelte';
import { invalidate } from '$app/navigation';
export let data;
onMount(() => {
const interval = setInterval(() => {
invalidate('data:now');
}, 1000);
return () => {
clearInterval(interval);
};
});
</script>
<h1>
{new Intl.DateTimeFormat([], {
timeStyle: 'full',
timeZone: data.timezone
}).format(new Date(data.now))}
</h1>
load() 関数内で fetch() を使うと依存関係が設定される。
依存関係の設定だけをしたい場合は fetch() の代わりに depends () を使う。
depends() の引数は URL ライクなら何でも OK、正規表現では ^[a-z]+:
になる。
Part 4 / Advanced loading / invalidateAll
<script>
import { onMount } from 'svelte';
import { invalidateAll } from '$app/navigation';
export let data;
onMount(() => {
const interval = setInterval(() => {
invalidateAll();
}, 1000);
return () => {
clearInterval(interval);
};
});
</script>
<h1>
{new Intl.DateTimeFormat([], {
timeStyle: 'full',
timeZone: data.timezone
}).format(new Date(data.now))}
</h1>
export async function load() {
return {
now: Date.now()
};
}
現在のページのロード関数をすべて再実行したい場合は invalidateAll() 関数を呼び出す。
この場合はロード関数内で fetch() や depends() が無くても再実行される。
invalidate(() => true)
と invalidateAll()
は異なり、前者では fetch() や depends() の呼び出しが必要となる。
12/1 (金) はここまで
20 分経過したので累計時間は 190 分、次は下記から始める。
12/5 (火) はここから
今日も 20 分くらいやっていこう。
Part 4 / Environment variables / $env/static/private
PASSPHRASE="open sesame"
import { redirect, fail } from '@sveltejs/kit';
import { PASSPHRASE } from '$env/static/private';
export function load({ cookies }) {
if (cookies.get('allowed')) {
throw redirect(307, '/welcome');
}
}
export const actions = {
default: async ({ request, cookies }) => {
const data = await request.formData();
if (data.get('passphrase') === PASSPHRASE) {
cookies.set('allowed', 'true', {
path: '/'
});
throw redirect(303, '/welcome');
}
return fail(403, {
incorrect: true
});
}
};
SvelteKit では Vite を使っているので .env だけでなく .env.local や .env.development なども使うことができる。
process.env にある環境変数も $env/static/private からアクセスすることができる。
クライアントサイドで import { PASSPHRASE } from '$env/static/private';
をするとエラーになる。
このインポートは +server.js か .server.js で終わるファイル、src/lib/server 以下のファイルでのみ行うことができる。
Part 4 / Environment variables / $env/dynamic/private
import { redirect, fail } from '@sveltejs/kit';
import { env } from '$env/dynamic/private';
export function load({ cookies }) {
if (cookies.get('allowed')) {
throw redirect(307, '/welcome');
}
}
export const actions = {
default: async ({ request, cookies }) => {
const data = await request.formData();
if (data.get('passphrase') === env.PASSPHRASE) {
cookies.set('allowed', 'true', {
path: '/'
});
throw redirect(303, '/welcome');
}
return fail(403, {
incorrect: true
});
}
};
アプリのビルド時ではなく実行時に与えられる環境変数を読み込みたい場合は $env/dynamic/private からインポートを行う。
インポートするものも env オブジェクトに変わる。
Part 4 / Environment variables / $env/static/public
PUBLIC_THEME_BACKGROUND="steelblue"
PUBLIC_THEME_FOREGROUND="bisque"
<script>
import {
PUBLIC_THEME_BACKGROUND,
PUBLIC_THEME_FOREGROUND
} from '$env/static/public';
</script>
<main
style:background={PUBLIC_THEME_BACKGROUND}
style:color={PUBLIC_THEME_FOREGROUND}
>
{PUBLIC_THEME_FOREGROUND} on {PUBLIC_THEME_BACKGROUND}
</main>
<style>
main {
position: fixed;
display: flex;
align-items: center;
justify-content: center;
left: 0;
top: 0;
width: 100%;
height: 100%;
font-size: 10vmin;
}
</style>
PUBLIC_ から始まる環境変数はクライアント側でも読み込むことができる。
システム名などクライアント側で共通の情報を管理するのにも便利そう。
Part 4 / Environment variables / $env/dynamic/public
<script>
import { env } from '$env/dynamic/public';
</script>
<main
style:background={env.PUBLIC_THEME_BACKGROUND}
style:color={env.PUBLIC_THEME_FOREGROUND}
>
{env.PUBLIC_THEME_FOREGROUND} on {env.PUBLIC_THEME_BACKGROUND}
</main>
<style>
main {
position: fixed;
display: flex;
align-items: center;
justify-content: center;
left: 0;
top: 0;
width: 100%;
height: 100%;
font-size: 10vmin;
}
</style>
プライベートな環境変数と同様にパブリックな環境変数でもビルド時ではなく実行時に読み込んだ値を使うことができる。
これは地味にすごい、同じことやろうとしたら結構大変だと思う。
内部的にはサーバーとクライアントでやり取りしていると思われる。
チュートリアルが完了した
9/8 から始まった約 3 カ月間のチュートリアルが完了した。
残りは下記のまとめをやっていこう。
- Hooks
- Page options
- Link options
- Advanced routing
- Advanced loading
- Environment variables
12/5 (火) はここまで
25 分経過したので累計時間は 205 分、次は下記のまとめから始める。
Hooks まとめ
handle
- フックとは SvelteKit のデフォルト動作を上書きする機能のこと。
- 最も基本的なフックは handle であり、src/hooks.server.js を作成して handle() 関数をエクスポートすることで作成できる。
- handle() 関数の第 1 引数としてオプションを受け取り、オプションには event や resolve が含まれる。
- event にはアクセスされたページの URL などが含まれる。
- resolve はルートの +page.server.js や +page.svelte の実行結果の Promise を返す関数であり、第 2 引数のオプションで transformPageChunk を指定することで HTML の書き換えなどができる。
- handle() 関数は Response オブジェクトを返せば良いので必ずしも resolve() を呼び出す必要はない。
The RequestEvent object
- handle() 関数に渡される event オブジェクトは API routes やフォームアクション、ページの load() 関数に渡されるものと同じ。
- locals はアプリで使用するデータを格納するのに適している。
handleFetch
- event オブジェクトには fetch() 関数が含まれている。
- この fetch() 関数は拡張されており、cookie や authorization ヘッダーの引き継ぎや相対リクエストが可能。
- API route などで fetch() 関数を呼び出した場合は HTTP リクエストは行われず、直接 GET() 関数などが呼ばれる。
- handleFetch() フックは fetch() 関数の動作をカスタマイズするために使用される。
handleError
- handleError() フックは予期しないエラーが発生した時の動作をカスタマイズできる。
- デフォルトの動作はコンソール出力だが例えば Slack などに通知することも可能。
- handleError() 関数の戻り値は +error.svelte ページで page ストアを使って参照できる。
12/7 (木) はここから
宣言を忘れてしまったが本日は 7:40 頃から開始した。
12/7 (木) はここまで
10 分経過したので累計時間は 215 分、次は Page options のまとめから始める。
12/8 (金) はここから
今日こそ 20 分くらいやっていこう。
Page options まとめ
Basic
- +page.js や + page.server.js、+layout.js や +layout.server.js では ssr や csr などのページオプションをエクスポートすることで設定できる。
- レイアウトの設定はすべての子孫に反映され、子孫のページやレイアウトは設定を上書きできる。
- ルートレイアウトでデフォルトの設定をしておき、個々のページやレイアウトで設定を変更するのがメジャーな使い方になる。
ssr
- SvelteKit では SSR がデフォルトになっている。
- コンポーネントによってはサーバー側でレンダリングできないものもある。
- 一例として window オブジェクトに即座にアクセスするコンポーネントが考えられる。
- SSR を CSR に切り替えるには +page.server.js で export const ssr = false; と書く。
csr
- csr を OFF にすることで JavaScript を実行しないようにできる。
- おそらくデフォルトでは ON になっている。
prerender
- 事前レンダリングとはリクエストの度ではなくビルド時に 1 回だけレンダリングすることを意味する。
- 事前レンダリングはサーバー負荷や表示速度の面でメリットがある。
- 一方、ビルド時間が長くなることや更新に再ビルドと再デプロイが必要になることがデメリット。
- 事前レンダリングはすべてのページで有効化できる訳ではない。
- すべてのリクエストに対して同じページ内容を返し、かつフォームアクションを使っていないページだけが事前レンダリングできる。
- ルートパラメーターを使っているページでも事前レンダリングを有効化できる。
- その場合は prerender.entries の設定を行う必要がある。
trailingSlash
- trailing slash とは URL 末尾のスラッシュ(/)のこと。
- SvelteKit では trailing slash はデフォルトで削除されるようになっている。
- 逆に trailing slash を付加したい場合は export const trailingSlash = 'always'; を実行する。
- trailing slash の削除を無効化したい場合は export const trailingSlash = 'ignore'; を実行する。
Link options まとめ
Preloading
- a タグに data-sveltekit-preload-data 属性を設けることでホバー/タップ時に事前読み込みができるので表示が速くなる。
- この属性は個々の a タグに付与することもできるが body などに付与することで全てのリンクに設定を反映できる。
- data-sveltekit-preload-data は指定がなければ hover になるが、tap や off も指定できる。
- data-sveltekit-preload-data の代わりに data-sveltekit-preload-code を使うことで JavaScript コードのみを読み込むこともできる。
- $app/navigation から preloadCode() や preloadData() 関数をインポートして script タグ内で事前読み込みを行うこともできる。
Reloading the page
- SvelteKit ではページ間のナビゲーションはページの再読み込みなしで行われる。
- a タグやそのコンテナに data-sveltekit-reload 属性を付与することでページの再読み込みを行うように設定できる。
- この他にもいくつかのリンクオプションがある。
- data-sveltekit-replacestate:ページ履歴を追加するのではなく書き換える。
- data-sveltekit-keepfocus:フォーカスを維持したままにする、検索ページなどで便利。
- data-sveltekit-noscroll:ページ内リンクをクリックした時にスクロールしないようにする。
Advanced routing まとめ
Optional parameters
- ディレクトリ名を [param] ではなく [[param]] とすることでパスパラメーターを省略可能にできる。
- 省略可能にしたことで +page.svelte と [[param]]/+page.svelte が衝突してしまうので、その場合は +page.svelte の方を削除する。
Rest parameters
- ディレクトリ名を
[path]
の代わりに[...path]
とすることで複数のパスセグメントにマッチできる。 - [...path] ディレクトリと同じ階層に他のディレクトリが存在しても問題ない。
- その場合は他のディレクトリへのマッチが優先され、いずれにもマッチしない場合に [...path] ディレクトリにマッチするようになる。
- レストパラメーターは末尾にある必要はなく
/items/[...path]/edit
や/items/[...path].json
にすることも可能。
Param matchers
- パスパラメーターを正規表現などでチェックしたい場合には param matchers を利用できる。
- param matchers を利用するには src/params に .js / .ts ファイルを作成し、match() 関数をエクスポートする。
- どの param matchers を使用する場合はディレクトリ名を例えば
[param=hex]
のようにする。
Route groups
- レイアウトを変更せずに共通のアプリケーションロジックを適用したい場合は route groups を利用できる。
- 典型的な例としてはユーザー認証が挙げられる。
- route groups を利用するには (authed) のような丸カッコでくくった名前でディレクトリを作成し、共通のアプリケーションロジックを適用したいディレクトリを移動する。
Breaking out layouts
- レイアウトをリセットするには
+page@b.svelte
のようにファイル名に @ を入れる。 -
a/b/c/+page@b.svelte
は c のレイアウトではなく b のレイアウトが使われる。 - ルートレイアウトにリセットするには
+page@.svelte
のように書く。 - ルートレイアウトはリセットすることができない。
Advanced loading まとめ
Universal load functions
- +page.js や +layout.js は universal load functions と呼ばれ、サーバーとクライアントの両方で実行される。
- server load functions からはシリアライズできなくてサーバーからクライアントに渡せないものを渡すのに便利。
- universal load functions はページロード時はサーバーとクライアントの両方で実行される。
- それ以降はクライアントのみで実行される。
Using both load functions
- server load functions と universal load functions は併用できる。
- server の方が最初に実行され、universal の方が後に実行される。
- universal の方から data 引数を通じて server の戻り値にアクセスできる。
- 戻り値はマージされないので、universal の方で明示的にリターンする必要がある。
Using parent data
- load() 関数では parent() 関数を実行することでレイアウトの load() 関数の実行結果の Promise を取得することができる。
- universal load functions は server と universal の両方のロード関数の実行結果を取得できる。
- server load functions は server のロード関数の実行結果しか取得できない。
- parent() を await する前にデータベースや API からデータを取得できる場合はそうした方が並列実行できるのでなるべく parent() は後から実行する方が良さそうだ。
Invalidation
- SvelteKit は何か入力が変化したと思われる時だけロード関数を再実行する。
- 何も変化していないにも関わらずロード関数を実行したい場合は invalidate() 関数を実行する必要がある。
- invalidate() 関数には文字列だけではなく関数を引数として与えることができる。
Custom dependencies
- load() 関数内で fetch() を使うと依存関係が設定される。
- 依存関係の設定だけをしたい場合は fetch() の代わりに depends () を使う。
- depends() の引数は URL ライクなら何でも OK、正規表現では
^[a-z]+:
になる。
invalidateAll
- 現在のページのロード関数をすべて再実行したい場合は invalidateAll() 関数を呼び出す。
- この場合はロード関数内で fetch() や depends() が無くても再実行される。
-
invalidate(() => true)
とinvalidateAll()
は異なり、前者では fetch() や depends() の呼び出しが必要となる。
Environment variables まとめ
$env/static/private
- SvelteKit では Vite を使っているので .env だけでなく .env.local や .env.development なども使うことができる。
- process.env にある環境変数も $env/static/private からアクセスすることができる。
- クライアントサイドで
import { PASSPHRASE } from '$env/static/private';
をするとエラーになる。 - このインポートは +server.js か .server.js で終わるファイル、src/lib/server 以下のファイルでのみ行うことができる。
$env/dynamic/private
- アプリのビルド時ではなく実行時に与えられる環境変数を読み込みたい場合は $env/dynamic/private からインポートを行う。
- インポートするものも env オブジェクトに変わる。
$env/static/public
- PUBLIC_ から始まる環境変数はクライアント側でも読み込むことができる。
- システム名などクライアント側で共通の情報を管理するのにも便利そう。
$env/dynamic/public
- プライベートな環境変数と同様にパブリックな環境変数でもビルド時ではなく実行時に読み込んだ値を使うことができる。
- これは地味にすごい、同じことやろうとしたら結構大変だと思う。
- 内部的にはサーバーとクライアントでやり取りしていると思われる。
まとめ完了
25 分経過したので累計時間は 240 分だった。
Part 1 は 305 分、Part 2 は 415 分、Part 3 は 270 分だったので合計では 1230 分、時間単位だと 20.5 時間となる。
よくここまで続いたものだと自分で自分を褒めてあげたい。
来週からはしばらく止まっていたライフプラン作成でも再開しようかな。