Svelteハンズオン
#Svelte
Svelteで掲示板サイトを作るハンズオン
完成品:https://svelte-bulletin-board-0624.netlify.app/
https://gyazo.com/8af4ce8ada4f46ce09fd445f9a4011d2
完成版コード:fuurin/svelte-bulletin-board
お急ぎの方はこれのmasterブランチをGit Clone
node.jsが入っていることを確認
$ node --version
$ yarn もしくは npm install
$ yarn dev もしくは npm run dev
http://localhost:5000 にアクセス
参考
(公式) Svelte • Cybernetically enhanced web apps
(公式チュートリアル) Introduction / Basics • Svelte Tutorial ← 1日もあれば全部目を通して思い出せる
Svelteで始める頑張らないフロントエンド生活 前編
Svelteで始める頑張らないフロントエンド生活 後編
Svelteのドキュメントを翻訳してみた - Qiita
すべての新しいWeb開発者にSvelteを推奨する10の理由
SvelteでWebサイトを作ってみて感じた魅力 - Qiita
ハンズオン
環境
VSCode
Svelte for VS Code 拡張を入れておくと良い
Node.js
筆者のバージョン
code: node
mac% node --version
v14.14.0
Hello Svelte!
ターミナルを開き、プロジェクトを作りたいディレクトリへ移動
$ npx degit sveltejs/template svelte-bulletin-board
npx: 公開されているNodeパッケージをローカルインストールなしで実行できるNode.jsのコマンド
npxでnodeモジュールを実行する - Qiita
degit: gitリポジトリをコピーしてくるNodeパッケージ
degit - npm
Ok to proceed? (y) が出たらそのままEnter
テンプレートから自動でSvelteプロジェクトが作成される
$ cd svelte-bulletin-board
$ code .
ターミナルからVisual Studio Codeを起動する方法【公式の方法】 - Qiita
以下、VSCodeのターミナルを開いて実行 (MacならCmd + Shift + @)
$ yarn
Svelteを使ったプロジェクトに必要なパッケージをpackage.jsonに基づき取得
npm installでも同じことができるが、以降は短くかけて高速なyarnを利用
$ yarn dev もしくは npm run dev
http://localhost:5000 にアクセス
VSCodeのターミナルに表示される http://localhost:5000 をCmd押しながらクリックでも開ける
https://gyazo.com/c2511e6ef7b6a4c59b2d369ae0aaf7dc
テンプレートを見てみる
https://gyazo.com/c3b5253b21d7766882d4a4c43ee136f0
public: rollupというwebpackっぽい何かで圧縮されたコードが入るディレクトリ。この中身がリリースされる。
global.css: アプリケーションの全ての要素に適用されるCSSを書くところ。邪魔なので中身を空にする。
index.html: アプリケーションの土台となるHTML 。
タイトルを適当に変更 (<title>Svelte掲示板</title>)
src: 開発の時はこの中身をメインで触る。
main.js: App.svelteを読み込んでindex.htmlで表示するために使ったりする。
propsはSvelteアプリケーションとその外の間でデータをやり取りするのに使える。
これによってReactやVueの中で部分的にSvelteを使うこともできる(はず)
しかし今回は使わないのでpropsは空にして良い。
App.svelte: デフォルトのSvelteファイル。Svelteで使うコードは拡張子が.svelte。主にこのファイルを変更していく。
App.svelteの中身
https://gyazo.com/dd88464a821cb9e4f6bd1adc4145bc31
SvelteではJavaScript、HTML、CSSっぽいものを1つの部品として扱う。(Vueと同じ単一ファイルコンポーネント)
script部:JavaScriptを書いて見た目を制御する。
style部:このコンポーネントにのみ有効なCSSを書く。
残り:Svelteの記法が使えるHTMLを書く。
Svelteで変数の中身を表示する
Svelteではscript部で宣言した変数をそのままHTMLに{}を使って表示できる。
code: src/App.svelte
<script>
// exportするとmain.jsのpropsを通じてnameを外部と共有できる。
// 今回App.svelteはトップのSvelteファイルで外部との共有はしないのでexportしなくても良い
let name = 'Komatsu'
</script>
<main>
<h1>Hello {name}!</h1> <!-- {}で囲むと宣言されているnameの内容を表示する -->
<p>...省略...</p>
</main>
https://gyazo.com/30ba89ded9fc9f1ff6c0930a26c5124a
CSSのh1にtext-transform: uppercase;が設定されているので全部大文字にされる
ちなみにファイルの変更があったときセーブするだけで画面が更新される (ホットリロード)
ボタンクリックで文字が変わるようにする
SvelteのHTMLではon:clickを使ってクリック時に関数を実行できる。
{#if 条件}、{:else} もしくは {:else if 条件}、{/if}を使って条件によって表示するものを切り替えられる
覚え方:# → 制御文の開始、: → 制御文の継続、/ → 制御文の終わり
code: src/App.svelte
<script>
let showFirstName = true
const toggle = () => showFirstName = !showFirstName
</script>
<p>
{#if showFirstName}
Shusei
{:else}
Komatsu
{/if}
</p>
<!-- on:clickのようにSvelte独自のHTML要素に設定する属性をディレクティブという -->
<button on:click={toggle}>Toggle</button>
https://gyazo.com/7f2cfcec25f077e9236a26f5441709b1 ↔https://gyazo.com/d8c52324dea3604dfb324ddc604994ed
変数の内容を変更すると自動的に画面へ反映される!
モダンJSフレームワークに特徴的なこの「リアクティブプログラミング」が非常に簡単に行える
ここからは本格的に掲示板サイトを作っていきましょう!
デザインフレームワークやコンポーネントライブラリを使って爆速開発
Svelte用のスタイリング済みコンポーネントライブラリは色々ある
Svelteで使えるコンポーネントライブラリをまとめてみた - Qiita
今回は有名なデザインフレームワークのBootstrapがベースになっているsveltestrapを使ってみる
導入しやすい
Bootstrap 自体が最も有名なデザインフレームワークの 1つ -> 情報が豊富!扱いやすい!
sveltestrapのドキュメントはStoryBookでしっかり整備されているので迷いにくい
Bootswatchという「テーマ」ごとに統一的なデザインを提供してくれるものとも併用できる
今回はFlatlyというテーマを使ってみる
https://gyazo.com/44888418e072591875ea99eb79ae86a8
導入
$ yarn add -D sveltestrap もしくは npm install --save-dev sveltestrap
$ yarn add bootstrap bootswatch もしくは npm install --save bootstrap bootswatch
sveltestrap自体はbootstrapを持たないので別途入れる
code: src/main.js
import 'bootswatch/dist/flatly/bootstrap.min.css'; // 追加。「flatly」のところがテーマ名。
ついでにXSS対策をしつつマークダウン記法をHTMLに変換してくれるsafe-marked.jsを使ってみる
$ yarn add safe-marked もしくは npm install --save safe-marked
これで準備完了。
App.svelteを以下のようにまるごと書き直してボタンがかっこよくなったら導入成功
code: src/App.svelte
<script>
import { Button, Container } from 'sveltestrap'
const hello = () => alert('Hello!')
</script>
<Container class="mt-4 mb-5">
<Button color="success" on:click={hello}>Push!</Button>
</Container>
<style>
</style>
https://gyazo.com/ccf9ca9c6a95003e63278af2e37f0233
掲示板アプリの部品、すなわちコンポーネントは大きく分けて3つ
NavBar (Webサイトっぽい見た目にするのに必要)
Comments一覧リスト
Form
NavBarを作る
Svelteはコンポーネントを組み合わせてアプリケーションを構築する。
適切にコンポーネント分けすることでコードの保守性と再利用性が高まる。
全部一つのコンポーネントに書くと「ここ直したいんだけどどこ見に行けばいいんだ...?」などとなる
NavBarコンポーネントを作ってApp.svelteで読み込んで使う。
code: src/NavBar.svelte
<script>
import { Navbar, NavbarBrand } from 'sveltestrap'
</script>
<Navbar color="primary" >
<NavbarBrand href="/">
<!-- デフォルトで用意されていたfaviconをNavBarのアイコンに使う -->
<img src="./favicon.png" width="36" alt="brand" />
<span class="h4">Svelte掲示板</span>
</NavbarBrand>
</Navbar>
code: src/App.svelte
<script>
import { Button, Container } from 'sveltestrap'
// 作ったNavBar.svelteを読み込む
import NavBar from './NavBar.svelte'
const hello = () => alert('Hello!')
</script>
<!-- 読み込んだNavBarを使う -->
<NavBar />
<Container class="mt-4 mb-5">
<Button color="success" on:click={hello}>Push!</Button>
</Container>
https://gyazo.com/2c5e599da9e7518611663ac9e597a28b
画面の上側に固定されるNavBarを、CSSを書かずsveltestrapによって簡単に作成できた。
コメント表示部を作る
{#each 配列とか as 要素}で繰り返しができる。繰り返し回数(インデックス)も取得可能。
script部でexportした変数はpropsとなり、外部とデータを双方向に共有することができる。
code: src/Comments.svelte
<script>
import { Card, CardHeader, CardBody } from 'sveltestrap'
// テキストをマークダウンに変換してくれる関数の用意。breaksオプションで改行を<br>に変換。
import { createMarkdown } from "safe-marked"
const markdown = createMarkdown({ marked: { breaks: true } })
// Commentsコンポーネントを使うApp.svelteから受け取る。
export let comments
</script>
{#each comments as comment, i} <!-- 第2引数(i)を設定すると繰り返し回数を取得できる -->
<Card class="my-3">
<CardHeader>
{i+1}: {comment.name} ({comment.timestamp})
</CardHeader>
<CardBody>
<!-- @htmlを使ってHTMLに変換したマークダウンを表示。safe-markedなのでXSS対策済み。 -->
{ @html markdown(comment.text) }
</CardBody>
</Card>
{:else}
<!-- eachの中でelseを使うと配列が空の時に表示する内容を指定できる! -->
コメントが投稿されていません。あなたが最初のコメントを投稿しましょう!
{/each}
code: src/App.svelte
<script>
import { Container } from 'sveltestrap' // Buttonは削除してしまう
import NavBar from './NavBar.svelte'
import Comments from './Comments.svelte' // 追加
// 追加 (中身はサンプル)
let comments = [
{
name: 'Aさん',
text: 'おはよう',
timestamp: '2021-04-07 07:00:00'
},
{
name: 'Bさん',
text: 'こんにちは\nみなさん',
timestamp: '2021-04-07 12:00:00'
},
{
name: 'Cさん',
text: 'こんばんは\nお疲れ様です\nお元気ですか?',
timestamp: '2021-04-07 19:00:00'
}
]
// helloは削除してしまう
</script>
<NavBar />
<Container class="mt-4 mb-5">
<!-- 追加。propsとしてcommentsを渡す。 -->
<Comments comments={comments}/>
<!-- Buttonは削除してしまう -->
</Container>
https://gyazo.com/63b8907c979e106ff51cbbe97024531f
それっぽくなってきた
コメント投稿フォームを作る
ここで初めてユーザからの入力を受け付ける
bindディレクティブを使うとフォームの入力値とJSの変数を双方向に連動させることができる。
Vueの双方向データバインディングと同様
on:clickだけでなく、イベントディスパッチャによって自作のイベントディレクティブを設定できる。
code: src/Form.svelte
<script>
import { Card, CardHeader, CardBody, FormGroup, Label, Input, Button } from 'sveltestrap'
// on:commentイベントを設定できるようにするため、イベントディスパッチャを作成
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
let name = ''
let text = ''
const comment = () => {
// nameかtextが空の時は投稿させない
if(!name || !text) {
alert('入力されていない項目があります。')
return
}
// nameとtextをまとめたオブジェクトを渡してon:commentに設定された関数を実行する
// {name, text}はES6の書き方で、{name: name, text: text}と同じ意味
dispatch('comment', {name, text})
// 連続投稿を防ぐため、投稿後textは空にする
text = ''
}
</script>
<Card>
<CardHeader>コメントを投稿する</CardHeader>
<CardBody>
<FormGroup>
<Label>名前</Label>
<!-- bind:valueディレクティブに変数を渡すとフォームに入力した値とJSの変数が双方向に連動する。 -->
<Input type='text' bind:value={name} />
</FormGroup>
<FormGroup>
<Label>コメント</Label>
<Input type='textarea' bind:value={text} />
</FormGroup>
<Button color='success' on:click={comment}>投稿</Button>
</CardBody>
</Card>
code: src/App.svelte
<script>
import { Container } from 'sveltestrap'
import NavBar from './NavBar.svelte'
import Comments from './Comments.svelte'
import Form from './Form.svelte' // 追加
let comments = [
{
name: 'Aさん',
text: 'おはよう',
timestamp: '2021-04-07 07:00:00'
},
{
name: 'Bさん',
text: 'こんにちは\nみなさん',
timestamp: '2021-04-07 12:00:00'
},
{
name: 'Cさん',
text: 'こんばんは\nお疲れ様です\nお元気ですか?',
timestamp: '2021-04-07 19:00:00'
}
]
// 追加
const handleComment = (comment) => {
// comments.pushでは表示が更新されないので再代入する形で記述する
// 参考:https://qiita.com/masakurapa/items/da3350d315edc438bd84
comments = ...comments, {...comment, timestamp: '2021-04-07 20:00:00'}
}
</script>
<NavBar />
<Container class="mt-4 mb-5">
<Comments comments={comments}/>
<!-- 線を追加 -->
<hr class="my-4">
<!-- 自作したon:commentイベントディレクティブを使う。 event.detailで渡されたオブジェクトを取得できる -->
<Form on:comment={(event) => {handleComment(event.detail)}} />
</Container>
https://gyazo.com/8a1f9d4e329bafd41872b9489f839373
コメントを記入して投稿するとコメント一覧に追加される。
https://gyazo.com/3dee2a10b1223242a3e656d7dd8a295c
空の項目があるとalertが出る。
コメント追加時、フェードインする
フェードイン大好きマン
code: src/Comments.svelte
<script>
...
import { fade } from 'svelte/transition' // 追加
...
</script>
{#each comments as comment, i}
<!-- transition:fadeをつけたdivで囲むことで、新たに要素が生成される時フェードインで出現する -->
<div transition:fade>
<Card class="my-3">
...
</Card>
</div>
{/each}
svelte/transitionでさくっと使うことができる5つのアニメーション - Qiita
コメントを投稿するとフェードインで出現する
これで基本的なフロントエンドの機能は完成!
CSSを使わずBootstrap、Bootswatchによるデザインとsveltestrapの既製コンポーネントだけでそれっぽいものができた!
https://gyazo.com/49f14b5504cc34710ea2f76cf1fdc646
API通信でみんなと掲示板の内容を共有する
※ 余談:APIが使えるようになるまで
APIができるまでモックが必要になることがある。その選定。
APIモックにSwagger使おうとしたけど こんなに詳細なモックじゃなくていい。ただパスとJSON設定して返せれば良い。
APIモックを使って開発速度を上げよう - Qiita
ローカルのお手軽モックJSONサーバ
REST APIを簡単にMockできるツールSmopeckの紹介 - Qiita
ローカルのちょっと色々できるモックJSONサーバ
Web API のモックサーバーとしても活躍、jsonbox.io | Articles | Riotz.works
JSONデータをPOSTすると保存してくれて同じパス、パラメータでアクセスすると保存したものを返してくれる。
これだ
jsonbox.io | A Free HTTP based JSON storageでURLを取得
code: make mock
mac% curl -X POST https://jsonbox.io/box_f3bc23b96ab0f70a8881/1 \
-H 'content-type: application/json' \
-d '[{"name": "Aさん",
"text": "こんにちは",
"timestamp": "2021-04-07 07:00:00Z"},
{"name": "Bさん",
"text": "こんにちは\nみなさん",
"timestamp": "2021-04-07 12:00:00Z"}]'
mac% curl -X POST https://jsonbox.io/box_f3bc23b96ab0f70a8881/2 \
-H 'content-type: application/json' \
-d '[{"name": "Aさん",
"text": "こんにちは",
"timestamp": "2021-04-07 07:00:00Z"},
{"name": "Bさん",
"text": "こんにちは\nみなさん",
"timestamp": "2021-04-07 12:00:00Z"},
{"name": "Cさん",
"text": "こんばんは\nみなさん\nお疲れ様です",
"timestamp": "2021-04-07 19:00:00Z"}]'
mac% curl -X POST https://jsonbox.io/box_f3bc23b96ab0f70a8881/3 \
-H 'content-type: application/json' \
-d '[{"name": "Aさん",
"text": "こんにちは",
"timestamp": "2021-04-07 07:00:00Z"},
{"name": "Bさん",
"text": "こんにちは\nみなさん",
"timestamp": "2021-04-07 12:00:00Z"},
{"name": "Cさん",
"text": "こんばんは\nみなさん\nお疲れ様です",
"timestamp": "2021-04-07 19:00:00Z"},
{"name": "Aさん",
"text": "こんばんは\nCさん",
"timestamp": "2021-04-07 19:30:00Z"},
{"name": "Bさん",
"text": "こんばんは\nCさん\nお疲れ様です",
"timestamp": "2021-04-07 20:00:00Z"}]'
作り直すならputかdelete
mac% curl -X DELETE 'https://jsonbox.io/box_f3bc23b96ab0f70a8881/1?q=name:*'
詳細な使い方:vasanthv/jsonbox: A Free HTTP based JSON storage. Now with protected boxes.
timestampが逆順で来ちゃうのでBASE_URL+'?sort=timestamp'とする
APIは今年結婚する同業の妻が作ってくれました!
table: API仕様
パス メソッド パラメータ 説明
/Messages GET name, text, timestampを持つコメントを全て配列にして取得する。
/Messages POST name, text name, textを持つコメントを投稿する。投稿時のtimestampは自動で設定される。
今回作ってもらったAPIサーバの構築方法について→ Go言語 + Cloud Functions + Cloud SQL によるバックエンド作成
API通信をPromiseで簡潔に書けるようにするライブラリのaxiosを導入 (fetchAPIとの違いについて)
$ yarn add axios もしくは npm install --save axios
API通信用のコードをまとめたファイルを作成する
code: src/api.js
import axios from 'axios'
const BASE_URL = 'https://...' // 別途配布します。配布されるまでは↑のjsonboxを使うと良いと思います。
function handleError(e) {
console.log(e)
alert('エラーが発生しました。')
}
export async function getComments() {
return await axios
.get(BASE_URL)
.then((res) => res.data)
.catch(handleError)
}
export async function postComment(comment) {
// パラメータをそのまま渡すとcontent typeが自動的にJSONになってしまう。
// フォームPOSTの形式にするためURLSearchParamsを通してパラメータとして設定する。
return await axios
.post(BASE_URL, new URLSearchParams(comment))
.then((res) => res)
.catch(handleError)
}
まずは入力フォームから改修する。
code: src/Form.svelte
<script>
import { Card, CardHeader, CardBody, FormGroup, Label, Input, Button } from 'sveltestrap'
import { postComment } from './api' // 追加
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
let name = ''
let text = ''
let sending = false // 投稿中は投稿ボタンをdisableにするための変数
async function comment() { // 中でawaitを使うためasync関数にする
if(!name || !text) {
alert('入力されていない項目があります。')
return
}
// 以下修正
sending = true
// async awaitの仕組みによってコールバック関数を渡さず、同期的に次の処理を書いていける。
// async awaitを使わなければ (jqueryの書き方だと)
// $.post(BASE_URL, {name, text})
// .success((res) => {
// dispatch('comment')
// text = ''
// })
// のように、ネストが深く見づらいコードになってしまう
await postComment({name, text})
dispatch('comment')
text = ''
sending = false
}
</script>
<Card>
<CardHeader>コメントを投稿する</CardHeader>
<CardBody>
<FormGroup>
<Label>名前</Label>
<Input type='text' bind:value={name} />
</FormGroup>
<FormGroup>
<Label>コメント</Label>
<Input type='textarea' bind:value={text} />
</FormGroup>
<!-- disabled={sending} 追加 -->
<Button color='success' on:click={comment} disabled={sending}>投稿</Button>
</CardBody>
</Card>
サンプルデータがなくなり、App.svelteはとても簡潔になる
code: src/App.svelte
<script>
import { getComments } from './api'
import { Container } from 'sveltestrap'
import NavBar from './NavBar.svelte'
import Comments from './Comments.svelte'
import Form from './Form.svelte'
let comments = []
async function updateComments() {
comments = await getComments()
}
updateComments()
</script>
<NavBar />
<Container class="mt-4 mb-5">
<Comments comments={comments}/>
<hr class="my-4">
<!-- updateCommentsに修正 -->
<Form on:comment={updateComments} />
</Container>
更新ボタン コンポーネントを作成
ここでもイベントディスパッチャを使う
code: src/Updater.svelte
<script>
import { Button } from 'sveltestrap'
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
const update = () => dispatch('update')
</script>
<Button color='secondary' on:click={update}>更新</Button>
code: src/App.svelte
// script部に追加
import Updater from './Updater.svelte'
// HTMLのhrの上に追加
<div class="mt-4">
<Updater on:update={updateComments}/>
</div>
ここまで書けたら動かしてみる
https://gyazo.com/8af4ce8ada4f46ce09fd445f9a4011d2
投稿すると自分のメッセージがPOSTされ、コメント一覧が更新される。
更新ボタンを押すとその時点で最新のコメント一覧が表示される。
みんなで共有の掲示板に投稿してコミュニケーションを取ってみましょう!
わいわいできたら完成!!
------------------------------------------------------- 研修はここまで ---------------------------------------------------------------
より発展的な内容
デプロイする
publicディレクトリ配下に配布用コードを作成するには
$ yarn build
デプロイ先には色々候補があるが、研修では立ち入らないことにする。
Netlifyで静的サイトのホスティングをする - Qiita 多分これが一番簡単。Githubに上げてそいつを指定してデプロイする。
Firebase : これもめっちゃ簡単。firebaseに登録し、firebase-toolsをnpmでインストールする必要がある。
Vercel (参考:Next.js#600c300fc9e8790000cbb09a):NuxtやNextで使いやすい。PRから自動でプレビューリリースを作ってくれるのが強力。
Heroku:Node.jsランタイムを使う。Heroku の Node.js サポート | Heroku Dev Center
GCP(GAE):ちゃんと触ったことないけどよく勧められる
AWS(EC2):静的ファイルだけで動くため、アクセス数が膨大にならなければそこまでやらなくてもいいかもしれない
Netlifyへのデプロイ方法
Githubにプロジェクトをpushする
https://gyazo.com/52c5bef3354a1664db047dac9d9df672
Netlifyにアクセス
右上の「Login」 -> 「GitHub」でログイン
「New site from Git」-> 「Github」 -> 「Authorize...」 -> 自分のアカウント名 -> 「Install」
もう一度「Github」をクリック -> さっきPushしたリポジトリを選択
「Publish Directory」にpublic/ と記述
https://gyazo.com/1a772cce3e1573f44cca5cd567c99e70
「Deploy Site」をクリックして、しばらく待ったらURLをクリックするとデプロイされていることがわかる
https://gyazo.com/364d70c6053723611ec9d63afbd6d02b
↑のURLの少し下の「Domain settings」からnetlifu.appより前のサイト名の部分を変更できる
https://gyazo.com/509537253b9e318a48303a8b930d76cb
もちろん自分の持っているカスタムドメインを「Set up a custom domain」から設定することもできる。
「Branch to Deploy」に設定したブランチにコミットがpushされると自動で再デプロイされる
状態管理
svelteは状態管理系も内包している。
code: (例) store.js
import { writable, derived } from 'svelte/store'
// 初期値0でcountという名前の書き込み可能storeを宣言
export const count = writable(0)
// storeを2倍した値を取得する関数
export const doubled = derived(count, $count => $count * 2)
// 0にする関数
export const reset = () => count.set(0)
// +1する関数
export const increment = () => count.update(n => n + 1)
これを.svelteファイルからimportして使う
他にも参考:https://svelte.dev/tutorial/writable-stores
重要なところはTODOでコメントアウトされていて自分で書く必要がある。=> インタラクティブに学べる!
ハンズオンで作ったものをsvelte/storeで書き直したもの
若干変更が多いのでこちらのPRを参照:stores version by fuurin · Pull Request #1 · fuurin/svelte-bulletin-board
code: src/stores.js
import { writable } from 'svelte/store'
import { getComments } from './api'
export const comments = writable([])
export async function updateComments() {
comments.set(await getComments())
}
commentsを保持したり子コンポーネントに渡して使ったりする必要がなくなるため、かなりコードが簡潔になる
簡単に使えて効果が大きいので、普段は最初からstoreの利用を前提とした設計をすると良い気がする
eachで回す時には$を先頭につけてやる必要があるので気をつける 参考
{#each $comments as comment, i}
配列に限らず、Storeの値を参照する時には$を先頭につけることになっている。名前の衝突を防ぐため?
タイマーで自動更新する
Updater.svelteでタイマーを使う
code: src/Updater.svelte
<script>
import { Button } from 'sveltestrap'
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
const UPDATE_INTERVAL = 5000 // ms
let timer = null
const update = () => dispatch('update')
const autoUpdate = (e) => {
if (e.target.checked) {
update()
timer = setInterval(update, UPDATE_INTERVAL)
} else if (timer !== null) {
clearInterval(timer)
}
}
</script>
<Button color='secondary' on:click={update}>
更新
</Button>
<label class='ml-3'>
<input type="checkbox" on:change={autoUpdate}/>
自動更新
</label>
ルーティング
svelte-spa-router を使うことで複数ページを作れる。
$ yarn add -D svelte-spa-router もしくは npm install --save-dev svelte-spa-router
コーディング例は以下の参考サイトを参照
svelte-spa-routerを使ってみる - Qiita
Svelteで始める頑張らないフロントエンド生活 後編
後述のSapperやSvelteKitではファイル名によるルーティングが可能。複数ページに渡るサイトを作る場合はそちらを推奨。
TypeScriptで書きたい方へ
SvelteのテンプレートにseupTypeScript.jsとかいう便利なものがある
$ node scripts/setupTypeScript.js .
$ yarn
code: .gitignore
.vscode/ ←追加
tsconfigで赤線が出るときはVSCodeを再起動
スクリプト部に<script lang="ts">のようにlangを設定するとTypeScriptを使えるようになる。
コード全体をTypeScriptに直してくれるわけではないので自分で直す。
Sapper
Docs • Sapper
Reactに対するNextみたいなもの。
ファイル名からルーティングを作成 & エラーページ表示
template.htmlによるベースレイアウトへのページ注入
静的生成
コード分割
しかし今ではSvelteKitがSapperの後継になる。Sapper 1.0は出ない。
svelte@next (SvelteKit)
次のSvelteはサーバレスファーストかもしれません - Svelte SummitでのRich Harris氏の講演
https://www.youtube.com/watch?v=qSfdtmcZ4d0&list=PL8bMgX1kyZThM1sbYCoWdTcpiYysJsSeu
Sapperは捨てられ、svelte@nextというものの開発が進行中
Next.jsやNuxt.jsのようなファイル名ルーティングや静的生成、コード分割などを行える。TSにも対応。
Webpackの代替だったRollupのさらなる代替としてSnowpackというものが利用されていた。と思いきやSnowpackもやめてVueの開発者であるEvan Youが開発したViteというビルドツールを利用するようになったとのこと。
発表の2週間前くらいにBeta版として公開!
SvelteKit is in public beta
Docs • SvelteKit
もうSvelteKitのチュートリアル記事も出てる
How to Build a Website with Svelte and Sveltekit - Prismic
非常にわかりやすく明確な英語なのでブラウザの自動翻訳で十分理解できる
PrismicというCMSを使っている。
CMSで作ったページの内容をJSONで取得して展開。
非開発者でもブログを作れるが、導入がやや面倒そう。
開発者ならカスタマイズ性が高くどんなフレームワークにも使えるのが利点だが、JSONを挟む以上パフォーマンスは落ちる。
nuxt.js×prismic でのブログ構築とヘッドレスCMSについて | gasekao.com