実践 Svelte 入門
実践 Svelte 入門
svelte-book/sample-app: 『実践 Svelte入門』(技術評論社)の書籍内で作成するサンプルアプリケーションのソースコード
Home · svelte-book/sample-app Wiki
1.1.1 Svelte の特徴
- 状態管理
- 変数を定義し、新しい値を代入するだけ
- 「普通の」HTML、JS
- JS
- 変数定義、値の代入
- HTML
- 変数
{hoge}
- 制御構文
-
{#if}
, etc
-
- イベントハンドラ
-
on:click={ ... }
, etc
-
- 変数
- JS
1.1.2 Svelte における「コンパイル」
- Svelte で書かれたコンポーネントはそのままブラウザに読み込まれない
- ランタイムなしで実行可能な形に変換されて読み込まれる
1.1.3 仮想 DOM を使わない
- 複雑化したフロントエンドの DOM 構造を適切に把握することは人間には難しい
- 仮想 DOM
- React
- コンパイル時に解決
- Svelte
- 仮想 DOM
1.2.2 HTML/CSS による画面構成要素の作成
App.svelte
なんかエラー出てる
Error in svelte.config.js
Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/vite-plugin-svelte' imported from /svelte-book-first-tutorial/svelte.config.js
npm install
し直して VS Code 再起動したら出なくなった
- Svelte の構文は普通の HTML / CSS に近い
- 導入の強い後押しになる
1.2.3 変数とイベントハンドラによる「カートに入れる」ボタンの挙動作成
1.2.4 配列と {#each} 構文による関連商品の表示
1.2.5 コンポーネントの分割
- VS Code で変数名等を一括で変更する
-
F2
: 「シンボルの名前変更」
-
- 画像スライダーをコンポーネントに分割
- コンポーネント
- 1 svelte ファイル = 1コンポーネント
- 管理する範囲を限定する
- 変更やテストが容易になる
- 変数名や関数名を簡単な名前に変えられる
- プロパティ
- コンポーネントの外部から値を設定できる
- 例)画像に関する情報を親コンポーネントから渡してもらう
- プロパティの定義
export let hoge
- プロパティの指定は HTML の属性と同様
<Slider hoge={...} />
- コンポーネントの外部から値を設定できる
- リアクティブステートメント
$: ...
- 依存関係にある別の状態に応じて状態を更新する
- 例)B, C の値が変わると A の値も変わる
$: A = B + C
- 例)B, C の値が変わると A の値も変わる
- コードが簡単になりバグも入りにくくなる
COLUMN - コンポーネントはそれぞれ独立した存在
2.1 環境構築
公式 Web REPL
Vite
$ npm create vite@latest project-name -- --template svelte
$ cd project-name
$ npm install
$ npm run dev -- --open
Vite (TS の場合)
$ npm create vite@latest project-name -- --template svelte-ts
Vite | Next Generation Frontend Tooling
(書籍から引用)
-
src/
- .js, .svelte など、アプリケーションのコード
- 必要に応じてコンパイルされる
- .js, .svelte など、アプリケーションのコード
-
public/
- サーバからそのまま配信される
-
vite.config.js
- Vite の設定ファイル
2.2.1 .svelte ファイルの構造
- コンポーネント
- コンポーネント内の関心事に集中できる
- 他のコンポーネントに影響しない
- 再利用しやすくなる
- コンポーネント内の関心事に集中できる
- Svelte コンポーネント
-
.svelte
ファイル- HTML, JS, CSS をまとめて記述
-
<script>
ブロック(省略可) -
<style>
ブロック(省略可) - テンプレート(上記以外)
-
- HTML, JS, CSS をまとめて記述
-
2.2.2 テンプレートの基本的な記法
2.2.3 スタイル
-
<style>
ブロック- スコープ化される
- 他のコンポーネントに影響しない
-
:global
修飾子:global(body) { ... }
- スコープ化を無効にする
- 全体に適用したい場合に使う
- スコープ化される
-
class
属性の省略記法- 例)
class={active ? 'active' : ''}
class:active={active}
-
class:active
(変数名とクラス名が同じ場合) -
class="button" class:blue={theme==='blue'} class:disabled
(複数・併用可)
- 例)
-
style
属性の省略記法-
style="color: red"
(通常) style:color="red"
-
style:color={color}
(値が変数の場合) -
style:color
(プロパティ名と変数名が同じ場合) - (複数・併用可)
-
2.2.4 ブロック
2.2.5 コンポーネントの使用
2.2.6 プロパティ
- プロパティ
- コンポーネントの動的な部分を指定する
- 例)ボタンのラベル、有効・無効の指定、など
- プロパティを作成する
- 子コンポーネント(プロパティを渡される側)
export let hoge
- プロパティに値を渡す
- 親コンポーネント
-
<Component hoge={値} />
- 「2.2.2 テンプレートの基本的な記法」と同じ記法が使用できる
-
{...$$props}
- 親コンポーネントから渡された全てのプロパティが格納される
-
{...$$restProps}
- 親コンポーネントから受け取ったプロパティのうち、export let で明示的に宣言したプロパティ以外のプロパティが格納される
- コンポーネントの動的な部分を指定する
2.2.7 スロット
- スロット
<slot />
- 子テンプレートで使用する
- 親コンポーネントからコンテンツを自由に挿入できる
- フォールバックコンテンツ
- スロットにコンテンツが挿入されなかった場合にデフォルトで表示する内容
<slot>フォールバックコンテンツ</slot>
- 名前付きスロット
- コンポーネントに複数のスロットを設ける場合、名前を付けて区別できる
- 通常の(名前のない)スロットとも併用可
- 子コンポーネント
-
slot
にname
属性を付与する <slot name="hoge" /> ... <slot />
-
- 親コンポーネント
- 名前付きスロットに挿入したい要素に
slot
属性を付与する-
slot
属性の付与されてない要素は全て名前のないスロットに挿入される
-
<Component><div slot="hoge"> ... </div><div> ... </div</Component>
- 名前付きスロットに挿入したい要素に
-
<svelte:fragment>
- スロットに挿入するコンテンツを
div
等の HTML 要素で囲みたくない場合に使用する <Component><svelte:fragment slot="hoge"> ... </svelte:fragment></Component>
- スロットに挿入するコンテンツを
-
$$slots
- コンポーネントで定義したスロットの名前がキーになったオブジェクトが格納された特別な変数
- 親コンポーネントから特定のスロットにコンテンツが挿入されているかの判断に使用できる
-
{#if $$slot.title} ... {/if}
-
title
スロットにコンテンツが挿入されている場合、true
になる
-
-
- スロットプロパティ
- スロットに挿入されたコンテンツに子コンポーネントから値を渡す場合に使用する
- 子コンポーネント
<slot プロパティ名={値} />
- 親コンポーネント
-
<Component let:プロパティ名={変数}> {変数} </Component>
- 変数にスロットで指定した値が入る
- プロパティ名は slot と合わせる
- 変数名は自由
- 名前付きスロットから値を渡される場合、
let:〜
はコンポーネントではなくslot
属性を付与した要素に追加する<Component><div slot="hoge" let:プロパティ名={変数}> {変数} </div></Component>
-
- 省略記法
-
<slot {hoge} />
-
<slot hoge={hoge} />
と同じ
-
-
<Component let:{hoge}
-
<Component let:hoge={hoge}
と同じ
-
-
COLUMN スロットを使うべきか、プロパティを使うべきか
- スロット
- 内容を自由に指定したい場合
- プロパティ
- 内容をある程度固定したい場合
<slot>
- Docs • Svelte
2.2.8 イベント
- DOM イベント
-
on:イベント名={関数}
<button on:click={handleClick}> ... </button>
<button on:click={() => alert('hoge')}> ... </button>
-
- イベント修飾子
- 慣例的によく行われる処理を指定できる記法
-
on:イベント名
に|
でつなぐ<button on:click|preventDefault={handleClick> ... </button>
- 複数指定可
-
- 修飾子
preventDefault
stopPropagation
passive
nonpassive
capture
once
self
trusted
- 慣例的によく行われる処理を指定できる記法
- コンポーネントイベント
- DOM イベントとは別に、コンポーネント独自のイベントを発生させる
createEventDispatcher()
- イベント転送
- 子コンポーネントのイベントを親コンポーネントにそのまま転送する
- 親コンポーネントでイベントハンドラを指定する
- 子コンポーネントのイベントを親コンポーネントにそのまま転送する
on:eventname, イベント修飾子, イベント転送
createEventDispatcher
2.2.9 ライフサイクル
- onMount
- onDestroy
- beforeUpdate
- afterUpdate
- tick
コード 2.2.49
let contents = Array.from({ length: 100 }, (_, i) => `投稿 ${i}`);
の _
は、Array.from()
メソッドのコールバック関数で配列の要素の値(i
はインデックス)が入るところだけど、
アンダースコア
_
自体は特別な意味は持たないが、コード内で値を無視することや、意図的に無名の変数またはパラメータを示すためによく使用される慣習
らしい
へー
_
の使用法は言語やコミュニティによって異なります。_
を無視される変数として使用する慣習は、可読性やコードの意図を明確にするためのツールとして広まってきました。ただし、コーディング規約やチームの合意に従うことが重要です。
- ライフサイクル
- ブラウザ上で実行される際の処理の流れ
- ライフサイクル関数
-
onMount
- コンポーネントの初回レンダリングが完了した直後
-
onDestroy
- コンポーネントが削除される直前
-
beforeUpdate
- DOM が更新される直前
-
afterUpdate
- DOM が更新された直後
-
tick
- 状態の変更が DOM に反映するまで待機する
-
- 処理実行のタイミング
- マウント時
- コンポーネントのマウント
-
<script>
ブロックの実行 beforeUpdate
- DOM 要素のレンダリング
onMount
afterUpdate
- 内部状態の更新時
- 内部状態の更新
beforeUpdate
- DOM 要素のレンダリング
afterUpdate
-
tick
の解決
- アンマウント時
- コンポーネントのアンマウント
onDestroy
- マウント時
3.1 コンポーネントのリアクティビティ
3.1.1 変数代入
3.1.2 $: プレフィックス
3.1.3 配列とオブジェクトの更新
3.1.4 入力のバインディング
(ユーザー入力を扱う要素の属性に対するバインディング)
- テキスト
- 数値
- チェックボックス
- ラジオボタン
- セレクトボックス
- グループ
- バインディング
- DOM 要素の属性値の更新を、コンポーネントの変数にも自動で反映する
-
bind:属性
<input type="text" bind:value={hoge}>
<input type="checkbox" bind:checked={isChecked}>
-
- グループ
- 複数の要素をグループ化して1つの変数にバインドする
- ラジオボタンやチェックボックスなど
- チェックボックスは複数選択可能なため変数は配列になる
- ラジオボタンやチェックボックスなど
-
bind:group={hoge}
<input type="radio" bind:gourp={hoge} value="...">
<input type="checkbox" bind:gourp={hoges} value="...">
- 複数の要素をグループ化して1つの変数にバインドする
- セレクト
-
<option>
の値が<select>
のvalue
属性にバインドした変数に代入される<select bind:value={hoge}><option value="...">〜</select>
-
multiple
の場合、複数選択可能なので変数は配列になる<select multiple bind:value={hoges}><option value="...">〜</select>
-
- DOM 要素の属性値の更新を、コンポーネントの変数にも自動で反映する
Docs • Svelte
bind:property
bind:group
3.1.5 メディア要素のバインディング
(メディアを扱う要素の属性に対するバインディング)
- メディア要素のバインディング
-
<video>
,<audio>
- 動画や音声の再生をコントロールする UI を操作した結果が変数に反映される
<video ... bind:currentTime={time}>
- 動画や音声の再生をコントロールする UI を操作した結果が変数に反映される
- 双方向
currentTime
playbackRate
paused
volume
muted
- read only
duration
buffered
played
seekable
seeking
ended
readyState
-
videoWidth
(video のみ) -
videoHeight
(video のみ)
-
Docs • Svelte
Media element bindings
HTMLMediaElement - Web API | MDN
3.1.6 コンポーネントバインディング
(コンポーネントのプロパティに対するバインディング)
3.1.7 this バインディング
- DOM 要素に対するバインディング
- Svelte コンポーネントに対するバインディング
-
this
バインディング- DOM 要素
- 属性ではなく、DOM 要素自体を変数にバインディングする
- テンプレート内の DOM 要素を簡単に取得できる
-
bind:this={変数}
-
<canvas bind:this={hoge} ... />
- 変数
hoge
から Canvas API を呼び出せる
- 変数
-
- コンポーネント
- コンポーネントも同様にバインディング可能
- コンポーネント内で export した const, class, function にアクセスできる
<Component bind:this={hoge} />
- DOM 要素
Docs • Svelte
Element directives > bind:this
Docs • Svelte
Component directives > bind:this
3.2 ストア
3.2.1 writable ストア
-
writable
ストア- 値の参照・更新の両方可
- 例)複数コンポーネントでログイン状態を真偽値として共有する
export const isLogin = writable(false)
- 例)複数コンポーネントでログイン状態を真偽値として共有する
- 操作
-
set(val)
- ストアの値を
val
に設定する
- ストアの値を
-
subscribe(callback)
- ストアを購読する
- ストアの値が変化した際、変化後の値を引数に callback が実行される
- 購読を解除する関数を戻り値として返す
- ストアを購読する
-
update(updater)
- ストアの値を更新する
- 現在の値を引数に updater が実行される
- 戻り値を新しい値としてストアに設定する
- 現在の値を引数に updater が実行される
- ストアの値を更新する
-
- 値の参照・更新の両方可
Docs • Svelte
svelte/store > writable
3.2.2 $ による自動購読
3.2.2 $ による代入
3.2.4 readable ストア
3.2.5 derived ストア
単一のストアに基づくストア
複数のストアに基づくストア
参考)
<input type="datetime-local"> - HTML: HyperText Markup Language | MDN
HTML5 <input type="datetime-local"> に現在時刻を設定するには - Qiita
moment.js・day.js よりも速くて軽い cdate ライブラリ - Qiita
-
derived
ストア- 他のストアの値に応じて値が変化するストア
Docs • Svelte
svelte/store > derived
3.2.6 カスタムストア
3.2.7 ストアのバインディング
- ストアのバインディング
-
writable
ストア、set
メソッドを持ったカスタムストアは、 「3.1 コンポーネントのリアクティビティ」で説明した各種バインディングの対象として指定できる -
<input ... bind:value={$store}>
- 自動購読と同様、ストア名の先頭に
$
をつける
- 自動購読と同様、ストア名の先頭に
-
第4章 Svelte の高度な機能
4.1 高度なテンプレート記法
4.1.1 キー付きの {#each} ブロック
4.1.2 {#key} ブロック
4.1.3 {@...} タグ
{@html}
{@debug}
{@const}
-
{@ ...}
タグ- ブロックとは異なり
{@ ...}
だけで完結する -
{@html 式}
-
{@html '<strong> 強調したテキストを出力する </strong>
}` - 式の内容を HTML として出力する
-
<
>
などがエスケープされない - HTML として正しくないと動作しない
-
- ユーザー入力などをそのまま出力すると XSS 脆弱性を生じるので注意する
-
-
{@debug 変数}
-
{@debug hoge}
{@debug hoge, foo, bar}
- 変数の値が変化すると、その値をログに出力する
-
console.log(...)
の代わりになる - ブラウザの開発者ツールを開いている場合、コードの実行を一時停止する
-
- 変数を複数指定可
- 変数以外は指定できない
- 変数の値が変化すると、その値をログに出力する
-
{@debug}
- 変数を指定しない場合、
debugger
文が挿入される- いずれかの状態が変化するとトリガーされる
- 変数を指定しない場合、
-
-
{@const 変数 = 式}
- 一時的な変数を定義する
-
{#if}
,{:else if}
,{:else}
,{#each}
,{:then}
,{:catch}
,<Component>
,<svelte:fragment>
の直下にのみ配置できる
- ブロックとは異なり
Docs • Svelte
{@html ...}
{@debug ...}
{@const ...}
4.1.4 <svelte:...>
タグ
<svelte:self>
<svelte:component>
<svelte:element>
<svelte:window>
<svelte:body>
<svelte:head>
<svelte:options>
<svelte:fragment>
-
<svelte:self>
- コンポーネント自身を表示するタグ
- このタグを書いた箇所にコンポーネント自身が表示される
- 無限ループを防ぐため
{#if}
,{#each}
ブロックの内側に入れる - または、コンポーネントのスロットに渡す
- 無限ループを防ぐため
-
<svelte:component>
- コンポーネントを動的に表示するタグ
-
<svelte.component this={Component} hoo={bar} />
-
this
プロパティに表示するコンポーネントの変数を渡す-
this
の値がfalse
の場合、何もレンダリングされない
-
-
-
<svelte:element>
- DOM 要素を動的に表示するタグ
-
<svelte:element this={'div'} attr={val}> ... </svelte:element>
<svelte:element this={\
h${level}`}> ... </svelte:element>`-
this
プロパティに表示する HTML 要素名を渡す-
this
の値がfalse
、存在しない要素名の場合、何もレンダリングされない -
this
の値がhr
,br
, 等の場合、子要素を持たせるとエラーになる
-
- 属性値を付与したい場合、
<svelte:element>
に直接記載する - バインディングは
bind:this
のみ使用可
-
-
<svelte:window>
-
Window
オブジェクトにイベントハンドラを設定する、一部のプロパティをバインディングするためのタグ- コンポーネントが破棄される際、イベントハンドラも
Window
オブジェクトから自動的に削除される- イベントハンドラを削除するコードが必要ない
- コンポーネントが破棄される際、イベントハンドラも
<svelte:window on:keydown={func} />
-
<svelte:window bind:scrollY={val} />
- バインドできるプロパティ
-
innerWidth
,innerHeight
,outerWidth
,outerHeight
,scrollX
,scrollY
,online
-
- バインドできるプロパティ
-
-
<svelte:body>
-
document.body
オブジェクトにイベントハンドラを設定するためのタグ- バインディングできるプロパティは無し
<svelte:body on:mouseenter={func} on:mouseleave={func} />
-
-
<svelte:head>
-
<head>
タグ内のコンテンツを指定するタグ <svelte:head> <title>...</title><meta ... /> </svelte:head>
-
-
<svelte:options>
- コンポーネントごとの設定を変更するタグ
- 設定可能なオプション
-
immutable
,accessors
,namespace
,tag
- ※ Svelte 4 で
tag
は廃止され、customElement
が追加された- Custom Elements with Svelte - Svelte 4 migration guide • Docs • Svelte https://svelte.dev/docs/v4-migration-guide#custom-elements-with-svelte
- ※ Svelte 4 で
-
-
<svelte:fragment>
- スロットに挿入するコンテンツを
div
等の HTML 要素で囲みたくない場合に使用する <svelte:fragment slot="hoge"> ... </svelte:fragment>
- スロットに挿入するコンテンツを
<svelte:self> 他
Docs • Svelte
4.2 モジュールコンテキスト
4.2.1 各インスタンス間での状態の共有
4.2.2 コンポーネント以外のエクスポート
4.3 モーション・トランジション・アニメーション
- DOM 要素の動きを制御するの3つの方法
- モーション
- 数値が滑らかに変化するストアを提供する
- トランジション
- 要素が表示・非表示する際の動きを指定する
- アニメーション
- 要素が入れ替わる際の動きを指定する
- モーション
4.3.1 モーション
- tweened
- delay オプション
- duration オプション
- easing オプション
- interpolate オプション
- spring
- stiffness オプション
- damping オプション
- precision オプション
tweened
spring
- モーション
- 数値が滑らかに変化するストア
- 時間をかけて徐々に値が変化する
- 例
- CSS アニメーション
- ストアを作成する関数
-
svelte/motion
からインポートする - 2つの関数
-
tweened
,spring
-
-
tweened
- 値が一定の時間をかけて変化する
- 値が徐々に変化する以外は通常の
writable
ストアと同様-
$
,set
なども使用可 - 3.2 ストア
-
- 指定できるオプション
-
delay
,duration
,easing
,interpolate
-
-
spring
- 値がバネの動きのように変化する
- 指定できるオプション
-
stiffness
,damping
,precision
-
-
- 数値が滑らかに変化するストア
4.3.2 トランジション
- ディレクティブ
- transition:
- in:
- out:
- 関数
- fade
- blur
- fly
- slide
- scale
- crossfade
- トランジション
- コンポーネントの状態(変数)の変化によって DOM 要素が表示・非表示する際、その動きをカスタマイズする仕組み
- 例
- フェードイン、フェードアウト
- 例
-
transision:
ディレクティブ<div transition:関数> ... </div>
- 表示・非表示の仕方を定義する関数を指定する
- パラメータの指定可
-
<div transition:関数={パラメータ(オブジェクト)}> ... </div>
- ディレクティブに指定した関数の第2引数に渡される
-
- 例
<div transition:fade={{ duration: 1000 }}>
-
in:
,out:
トランジション<div in:関数 out:関数> ... </div>
- 表示・非表示の仕方を別々に指定する場合
- 片方だけの指定可
- 指定する関数が同じ場合は
transition:
を使用する方が良い
- 関数
-
svelte/transition
-
fade
,blur
,fly
,slide
,scale
,draw
,crossfade
-
- 独自関数
-
- コンポーネントの状態(変数)の変化によって DOM 要素が表示・非表示する際、その動きをカスタマイズする仕組み
Docs • Svelte
transition:fn
in:fn / out:fn
4.3.2 アニメーション
参考)
Aerotwist - FLIP Your Animations
- アニメーション
- ブロック内の要素の位置が変わる際の動き(アニメーション)をカスタマイズする仕組み
- 要素の追加・削除では動作しない
- キー付き
{#each}
ブロック内でのみ使用可 -
animate:
ディレクティブ<div animate:関数> ... </div>
-
{#each}
の直下のみ有効 - アニメーションの挙動を定義する関数を指定する
- パラメータの指定可
<div animate:関数={パラメータ(オブジェクト)}> ... </div>
- 関数
-
svelte/animate
flip
- 独自関数
-
- ブロック内の要素の位置が変わる際の動き(アニメーション)をカスタマイズする仕組み
Docs • Svelte
animate:fn
4.4.1 コンテキスト API の使い方
- コンポーネント
- 親コンポーネントから子コンポーネントに対してデータを共有する仕組み
- 一種のキーバリューストアと想定可
- コンテキスト API
-
setContext
(親),getContext
(子) - コンポーネントの初期化時に呼び出す必要がある
- 任意の箇所で値を読み書きできない
- 例)
onMount
、イベントハンドラ
- 例)
- 任意の箇所で値を読み書きできない
-
- 例)
-
<canvas>
の2Dコンテキストをコンポーネント間で共有する
-
- 親コンポーネントから子コンポーネントに対してデータを共有する仕組み
Docs • Svelte
setContext, getContext
COLUMN キーの重複を回避する
-
Symbol()
を使用することで一意なキーを作成できる
Symbol (シンボル) - JavaScript | MDN
4.4.2 コンテキストの特徴とストアとの比較
- コンテキストの特徴
- 任意のコンポーネント間でデータのやりとりができない
- 先祖・子孫間のみ可
- リアクティブではない
- コンテキストの値を変更してもコンポーネントは再レンダリングされない
- コンポーネントのインスタンス毎に別々の値を保持する
- 任意のコンポーネント間でデータのやりとりができない
- ストアとの比較
- コンテキスト
- 親子関係が定まっているコンポーネント間でデータを共有する場合
- ストア
- 親子関係が定まっていないコンポーネント間でデータを共有する場合
- リアクティブ性が必要な場合
- コンテキスト
4.5 アクション
- アクション
- DOM 要素に Svelte コンポーネントのようなライフサイクル管理の仕組みを提供する
- DOM 要素が作成された際に呼び出される関数
4.5.1 アクションの基本的な使い方
第5章 SvelteKit による複数ページアプリケーションの開発
5.1 SvelteKit の基本と導入
5.1.3 SvelteKit プロジェクトのファイル構造
5.3 デモアプリケーションの実装を読み解く
5.2.1 ページを表す .svelt ファイル
5.2.2 レイアウト ー 複数ページに共通の要素を配置
5.2.3 フォームアクション ー プログレッシブな Web アプリケーションを構築する仕組み
参考)
オプショナルチェーン (?.) - JavaScript | MDN
?. 演算子の機能は . チェーン演算子と似ていますが、参照が nullish (null または undefined) の場合にエラーとなるのではなく、式が短絡され undefined が返されるところが異なります。
?. を . の代わりに用いることで、 JavaScript が obj.first.second にアクセスしようとする前に obj.first が null または undefined でないことを暗黙的に確かめるようになります。obj.first が null または undefined であった場合、式が自動的に短絡され、 undefined が返ります。
Null 合体演算子 (??) - JavaScript | MDN
Null 合体演算子 (??) は論理演算子の一種です。この演算子は左辺が null または undefined の場合に右の値を返し、それ以外の場合に左の値を返します。
Null 合体演算子と共に使う
Null 合体演算子はオプショナルチェーンの後につけることで、値が存在しなかったときの既定値を指定することができます。
let customer = {
name: "Carl",
details: { age: 82 }
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city
オプショナルチェーン (?.) - JavaScript | MDN
5.3 EC アプリケーションの拡張
5.3.1 ① SvelteKit プロジェクトの作成
5.3.2 ② 商品ページに対応するルートの作成
5.3.3 ③ 商品データとカートデータの取得
5.3.4 ④ フォームアクションでのカートへの追加
参考)
c - Why does ENOENT mean "No such file or directory"? - Stack Overflow
It's an abbreviation of Error NO ENTry (or Error NO ENTity), and can actually be used for more than files/directories.
カートの情報を保存する data/cart.json
ファイルは存在するが内容が空(JSON データとして不完全)の場合、エラーになる
SyntaxError: Unexpected end of JSON input
(内容だけ削除しないでファイルごと削除する or 空の配列 []
を入れておく)
5.3.5 ⑤ 「おすすめ商品」の表示
参考)
フェッチ API - Web API | MDN
参考)
$app/navigation
afterNavigate
現在のコンポーネントがマウントされるときや、新しい URL に移動するときに、与えられた callback を実行するライフサイクル関数です。
Modules • Docs • SvelteKit https://kit.svelte.jp/docs/modules#$app-navigation-afternavigate
参考)
Snapshots • Docs • SvelteKit
サイドバーのスクロールポジションや、<input> 要素の中身などの、一時的な DOM の状態(state)は、あるページから別のページに移動するときに破棄されます。
例えば、ユーザーがフォームに入力し、それを送信する前にリンクをクリックして、それからブラウザの戻るボタンを押した場合、フォームに入力されていた値は失われます。入力内容を保持しておくことが重要な場合、DOM の状態を スナップショット(snapshot) として記録することができ、ユーザーが戻ってきたときに復元することができます
第6章 SvelteKit リファレンス
6.1 SvelteKit の主要な概念
6.1.1 ページルート
6.1.2 サーバールート
6.1.3 フォームアクション
6.1.4 ルーティング
6.1.5 レイアウト
6.1.6 SvelteKit の実行モデル
6.2 ページルート
6.2.1 +page.svelte
6.2.2 +page.js と +page.server.js
6.3 フォームアクション
6.3.1 フォームアクションの基礎
6.3.2 プログレッシブなエンハンスメント
6.4 サーバールート
6.5 ルーティング
6.5.1 ルート
6.5.2 ルートに配置できるファイル
6.5.3 高度なルーティング
6.6 レイアウト
6.6.1 レイアウトの基礎
6.6.2 レイアウトのネスト
6.6.3 レイアウトのネストのリセット
6.7 フック
6.7.1 SvelteKit のフック
6.7.2 handle
6.7.3 handleFetch
6.7.4 hadleError
6.8 ヘルパーモジュール
6.8.1 $app/environment
- 実行環境に関する情報
6.8.2 $app/forms
- フォームアクションに関するヘルパー
6.8.3 $app/navigation
- ページ移動に関するヘルパー
6.8.4 $app/paths
- パスに関するヘルパー
6.8.5 $app/stores
- アプリケーションレベルのストア
ハイドレーションとは?
参考)
Time to interactive (対話までの時間) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN
TTI は 2018 年に Web Incubator Community Group によって提案されたもので、ページまたはアプリケーションに有用なコンテンツが含まれ、メインスレッドがアイドル状態になり、イベントハンドラーの登録など、ユーザーの操作に自由に応答できるようになるメトリクスを提供します。
Resumable - Qwik
Resumability is about pausing execution in the server and resuming execution in the client without having to replay and download all of the application logic.
A good mental model is that Qwik applications at any point in their lifecycle can be serialized and moved to a different VM instance (server to browser). There, the application simply resumes where the serialization stopped. No hydration is required. This is why we say that Qwik applications don't hydrate; they resume.
6.8.6 @sveltejs/kit
6.8.7 $env
- 環境変数へのアクセスを提供するモジュール
6.9 ビルドとデプロイメント
6.9.1 設定が不要なホスティングサービス - adapter-auto
6.9.2 Node サーバーとしてのビルド - adapter-node
6.9.3 静的サイトの生成と SPA モード - adapter-static
第7章 MongoDB と Versel による本番環境の構築
7.1 SvelteKit アプリケーションと本番環境
7.1.1 開発環境について/サンプリアプリケーションについて
7.1.2 本番環境・ビルド・デプロイ
7.2 MongoDB の導入
7.2.2 MongoDB Atlas でデータベースを作成
7.2.3 mongodb パッケージの導入と接続情報の管理
7.2.4 カートを MongoDB で実装
MongoTopologyClosedError: Topology is closed
接続できないな?と思ったら .env
のプロパティ名が間違ってた
7.2.5 商品を MongoDB で実装
7.3 Vercel へのデプロイ
7.3.1 GitHub のセットアップ
7.3.3 MongoDB Atlas のインテグレーションを導入
7.3.6 動作確認
第8章 Auth0 によるパスワードレスログイン実装とセッション管理
8.1 Auth0 の準備
8.1.1 パスワードレス認証とは
8.2 ログインフローの実装
8.2.4 コールバック URL の実装
8.2.5 セッション情報をデータベースに保存
8.2.6 ログインの動作確認
8.3 ログインユーザーの判定と表示
8.3.1 ログインユーザー情報の取得
8.3.2 ログイン中のユーザーの表示
8.3.3 ログアウト機能
8.4 ユーザーごとのカート作成
8.4.1 ユーザーIDごとにカートを作成
todo)
-
カート画面/cart
の修正もする500 エラー商品情報が表示されない
商品詳細ページの関数呼び出し、ボタン処理の変更に習って修正で done
8.5 Vercel へのデプロイ
参考)
adapter-vercel
Vercel • Docs • SvelteKit https://kit.svelte.jp/docs/adapter-vercel
Deploy Status > Building のログに出る ↓
If you plan on staying on this deployment platform, consider replacing @sveltejs/adapter-auto with @sveltejs/adapter-vercel. This will give you faster and more robust installs, and more control over deployment configuration.
8.5.1 Auth0 を使うための準備
COLUMN 最新情報の取得方法
- GitHub
- sveltejs/svelte: Cybernetically enhanced web apps https://github.com/sveltejs/svelte
- sveltejs/kit: web development, streamlined https://github.com/sveltejs/kit
- Discord
- Discord Svelte サーバー https://discord.com/invite/svelte
- Discord Svelte Japan サーバー https://discord.com/invite/YTXq3ZtBbx
- 他
- The (Unofficial) Svelte JS Newsletter | Dani Sandoval | Substack https://svelte.substack.com/
- Blog • Svelte 日本語サイト https://svelte.jp/blog
- Svelte Summit Spring 2023: The worlds biggest Svelte Conference https://www.sveltesummit.com/
第9章 ユーザー体験の改善 - OGP タグとプリレンダリング
9.1 OGP タグの追加
9.1.1 OGP タグと JavaScript アプリケーション
9.1.2 商品ページに OGP タグを追加
参考)
$page
store
Types • Docs • SvelteKit https://kit.svelte.jp/docs/types#public-types-page
参考)
The Open Graph protocol
9.1.3 SSR の無効化
9.1.4 CSR の無効化
9.2 プリレンダリング
9.2.1 商品ページのプリレンダリング
9.2.2 カートページの準備
COLUMN プリレンダに向くページと向かないページ
9.2.3 カート情報のクライアントサイドでの読み込み
9.2.4 「カートに入れる」ボタンの挙動を改善
9.2.5 プリレンダリングの動作確認
参考文献
- Introduction / Basics • Svelte Tutorial https://svelte.dev/tutorial/basics
- Introduction / Basics • Svelte Tutorial https://svelte.jp/tutorial/basics
- Docs • Svelte https://svelte.dev/docs
- Docs • Svelte https://svelte.jp/docs
- Introduction • Docs • SvelteKit https://kit.svelte.dev/docs/introduction
- イントロダクション • Docs • SvelteKit https://kit.svelte.jp/docs/introduction
- FAQ • Svelte https://svelte.dev/faq
- FAQ • Svelte https://svelte.jp/faq
- FAQ • SvelteKit https://kit.svelte.dev/faq
- FAQ • SvelteKit https://kit.svelte.jp/faq
- vite-plugin-svelte/docs/faq.md at main · sveltejs/vite-plugin-svelte · GitHub https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md
サポートページ:実践 Svelte入門:|技術評論社