LoginSignup
2
0

SvelteKit × Cloudflare Workers(Pages Functions)でローカル環境でCloudflare KVを利用する

Last updated at Posted at 2023-11-09

はじめに

ちょっとした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が実行される。
image.png

※ただし注意が必要で、あくまでJavaScriptなのでNode.jsのモジュールはそのまま利用できない。つまり、Node.jsの標準モジュールに依存する実装は動かない。動かすにはNode.js compatibilityに書かれているような対応が必要。SveltKitの@sveltejs/adapter-cloudflareではビルドエラーになる(内部的にはesbuildのplatform: 'browser'の設定になっているため。

基本的なWokerの実装について

Get started guideに書かれている通りにやってみると簡単にWorkers(サーバーレスのアプリ)を開発できる。

create-cloudflareにはいくつかのテンプレートがあるが、hello-worldを見ると以下のようなコードになっている。

hello-world
export default {
	async fetch(request, env, ctx) {
		return new Response('Hello World!');
	},
};

※他にもopenapiなど色々なテンプレートがあるみたい。

WorkerからのCloudflare KVの呼び出し方法

WorkerからCloudflareの各リソース(KVD1など)を利用するにはBindingsに書かれているように、Wokerに対してリソースを紐づける設定が必要になる。

具体的にはwrangler.tomlというファイルに以下のような設定を行う(詳細はKV namespacesを参照)。

wrangler.toml
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にアクセスする

方法としてはwranglerpages devコマンドを利用する。具体的には、ローカル環境なのでダミーでいいのでwrangler.tomlを以下のように定義する。

wrangler.toml
kv_namespaces = [
    { binding = "first_kv", id = "hoge" }
]

あとは、vite buildでビルドを行い、以下のpages devコマンドでCloudflare Pagesをエミュレートすればいい。すると、以下のようにSveltKitで実装したものがちゃんとSSRで描画され、またサーバーへのリクエストがログに出ていることが確認できる。
image.png

今回、以下のような画面でボタンをクリックしてGET:/api/kv-testを呼び出すような実装をしていたが、上記のログからと以下のスクショからうまく動いていることが確認できる。

ボタンクリック前 クリック後
image.png image.png

上記のような方法であれば、実際のCloudflare KV上にアクセスすることなく、アプリケーションのテストなどを行うことができるだろう。

ちなみに、いったいどこにデータがあるのか?だが、.wrangler/state/v3/kv/hoge/blobs以下にファイルとして存在しているみたい。
image.png

おまけ

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へのアクセス認可)を求められる。
image.png

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

image.png

本番環境でのバインディングの設定方法

wranglerコマンドからも同じことはできると思うが、GUIでやるなら以下から設定できる。

※注意点として、バインディングの設定は次のDeployから反映されるので、すでにDeploy済みのWorkerには反映されない。

image.png
image.png

ちなみに、Worker(Pages Function)のログはDeployの詳細ページから確認できる。
image.png

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でやる必要はないかも。

  1. 質問・回答のセットと、その質問・回答からタグを作ったものをDBに保存しておき、ユーザーからの質問からタグを生成し、そのタグの一致度が高いものを回答の候補にする。その回答の候補からユーザーへの質問に最もよいと思えるものをChatGPTに聞き、ChatGPTの応答をBotの応答として返す。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0