はじめに
ちょっとしたBotアプリ1を実装したくなり、その際にSveltKitで実装することにした。そしてDeploy先の環境としては、色々アクセス制御等が楽なCloudflare Pagesでやってみることを考えた(@sveltejs/adapter-cloudflareというCloudflare環境向けのビルドツールがあることもその理由)。
今回はそのアプリを実装する中で、KVSであるCloudflare KVを利用したくなった際に、Deployする前のローカルの開発環境で本番のKVと同じように開発をする方法はないものかと思い、調査してみたので、その備忘録を残そうと思う。
ライブラリなどのバージョンは以下。
- "@sveltejs/adapter-cloudflare": "^2.3.3",
- "@sveltejs/kit": "^1.27.1",
- "svelte": "^4.2.2",
- "wrangler": "^3.15.0"
- Node.js:v18.17.0
Cloudflare WorkersからKVを利用する方法について
SveltKitでの話の前に、まずは、Cloudflare Workersとは?について触れ、Wokerの実装がどのようなものなのか?を簡単に見ていく。次に、そのWokerからCloudflareの他のリソース(KVやD1など)を利用する方法を確認する。
Cloudflare Workersとは?
高パフォーマンスなサーバーレス実行環境(エッジコンピューティング環境)で、その環境ではJavaScript(V8)を実行することが可能なので、このサービスを利用するとサーバーレスアプリケーション構築することができる。
図は公式のものがわかりやすいと思うが、CloudflareのCDNのエッジでJavaScriptが実行される。
※ただし注意が必要で、あくまでJavaScriptなのでNode.jsのモジュールはそのまま利用できない。つまり、Node.jsの標準モジュールに依存する実装は動かない。動かすにはNode.js compatibilityに書かれているような対応が必要。SveltKitの@sveltejs/adapter-cloudflare
ではビルドエラーになる(内部的にはesbuildのplatform: 'browser'の設定になっているため。
基本的なWokerの実装について
Get started guideに書かれている通りにやってみると簡単にWorkers(サーバーレスのアプリ)を開発できる。
create-cloudflare
にはいくつかのテンプレートがあるが、hello-worldを見ると以下のようなコードになっている。
export default {
async fetch(request, env, ctx) {
return new Response('Hello World!');
},
};
※他にもopenapi
など色々なテンプレートがあるみたい。
WorkerからのCloudflare KVの呼び出し方法
WorkerからCloudflareの各リソース(KVやD1など)を利用するにはBindingsに書かれているように、Wokerに対してリソースを紐づける設定が必要になる。
具体的にはwrangler.toml
というファイルに以下のような設定を行う(詳細はKV namespacesを参照)。
kv_namespaces = [
{ binding = "<TEST_NAMESPACE>", id = "<TEST_ID>" }
]
上記のように設定することで、Worker内では以下のようにenv.TEST_NAMESPACE.put()
などのKV操作APIを実行できるようになる(詳細はInteract with your KV namespaceを参照)。
export default {
async fetch(request, env, ctx) {
await env.TEST_NAMESPACE.put("KEY", "VALUE");
const value = await env.TEST_NAMESPACE.get("KEY");
if (value === null) {
return new Response("Value not found", { status: 404 });
}
return new Response(value);
},
};
SveltKitでのKVの利用方法
SveltKitの場合、上記のWorkerからのCloudflare KVの呼び出し方法でみたBindingsが少し違っていて、Bindingsに書かれている通り、platform
プロパティからKVにアクセスできるようにしてくれるので、以下のような実装ができる(@sveltejs/adapter-cloudflare
を利用する場合)。
import { json } from '@sveltejs/kit';
export async function GET({ platform }) {
await platform.env.first_kv.put('key', JSON.stringify({ value: 'value' }));
const x = await platform.env.first_kv.get('key');
return json({ x }, { status: 200 });
}
ローカル環境でKVにアクセスする
方法としてはwranglerのpages devコマンドを利用する。具体的には、ローカル環境なのでダミーでいいのでwrangler.toml
を以下のように定義する。
kv_namespaces = [
{ binding = "first_kv", id = "hoge" }
]
あとは、vite build
でビルドを行い、以下のpages dev
コマンドでCloudflare Pagesをエミュレートすればいい。すると、以下のようにSveltKitで実装したものがちゃんとSSRで描画され、またサーバーへのリクエストがログに出ていることが確認できる。
今回、以下のような画面でボタンをクリックしてGET:/api/kv-test
を呼び出すような実装をしていたが、上記のログからと以下のスクショからうまく動いていることが確認できる。
ボタンクリック前 | クリック後 |
---|---|
上記のような方法であれば、実際のCloudflare KV上にアクセスすることなく、アプリケーションのテストなどを行うことができるだろう。
ちなみに、いったいどこにデータがあるのか?だが、.wrangler/state/v3/kv/hoge/blobs
以下にファイルとして存在しているみたい。
おまけ
Cloudflare KVを利用した経緯(Cloudflare WorkerではNode.jsの標準モジュールは利用できないので注意)
実はKVを利用したかったわけではなく、KVSとしてはRedisなどのリッチなものを利用したかった。Redisのサーバーレス版としてはUpstashなどがあったりするのでそれを利用しようと考えていたが、その時にREST APIがあることを忘れており、ioredisなどのNode.jsライブラリを利用しようとしていた。。。
そのため、@sveltejs/adapter-cloudflare
を利用してビルドするとCloudflare adapter: Could not resolve "path" and "fs"にあるようなエラーが発生し、それならCloudflareにあるKVを使ってみるか、というわけで利用してみた。
wranglerの初回インストールについて
一番最初にwrangler
のコマンドを実行する際に、ログイン(コマンドラインからのCloudflareへのアクセス認可)を求められる。
OAuth2.0の認可フローになっているので、認可するとコールバックで以下のようなリンクにとび、認可完了画面が表示される。
http://localhost:8976/oauth/callback?code=5ntORsEyBHMl0V8sZx9Dpgwktu0WbS6pqulLK6kgTn4.F95HOJ8ggrH1uBOIKDv72FHcpmnrJAYW91s1CKCTF8o&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20ssl_certs%3Awrite%20constellation%3Awrite%20ai%3Aread%20offline_access&state=rFdbAdFV~~JHvV4LxQkHbeMSBBX~VpR2
本番環境でのバインディングの設定方法
wrangler
コマンドからも同じことはできると思うが、GUIでやるなら以下から設定できる。
※注意点として、バインディングの設定は次のDeployから反映されるので、すでにDeploy済みのWorkerには反映されない。
ちなみに、Worker(Pages Function)のログはDeployの詳細ページから確認できる。
SveltKitのHMR(Hot Module Replacement)とセットでwrangler pages dev
を実行するのはできない?!
wrangler pages dev
でローカルの開発環境でCloudflare KVをエミュレートして開発はできるが、1点困ったことにvite dev
では@sveltejs/adapter-cloudflare
を利用したビルドはされないので、vite build
を行う必要がある。となると、毎回ファイルの変更ごとにビルドし直しになるので面倒…ということがある。
この問題を解決するには、nodemonを利用できる。以下のようにnodemonでビルドコマンドを実行することで、src以下の変更を検知して再度ビルドを走らせてくれる。
$ npx nodemon --watch src --exec 'yarn build'
wrangler pages dev
のコマンドも同様に、できるかな~と思ったがうまくいかなかった…。この辺り、解決する方法はあるのだろうか…。過去に同じような話をしているissueは見つけたが、解決はしていなさそう…。
うまくいかなかったコマンドは以下。
$ npx nodemon --watch .svelte-kit/cloudflare --exec 'npx wrangler pages dev .svelte-kit/cloudflare'
$ npx nodemon --watch .svelte-kit/output --exec 'npx wrangler pages dev .svelte-kit/cloudflare'
$ npx nodemon --watch src --exec 'npx wrangler pages dev .svelte-kit/cloudflare'
※vite build --watch
というコマンドもあるので、SveltKitのビルドの方はnodemonでやる必要はないかも。
-
質問・回答のセットと、その質問・回答からタグを作ったものをDBに保存しておき、ユーザーからの質問からタグを生成し、そのタグの一致度が高いものを回答の候補にする。その回答の候補からユーザーへの質問に最もよいと思えるものをChatGPTに聞き、ChatGPTの応答をBotの応答として返す。 ↩