2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cloudflare WorkersとKVとD1をHonoで使ってみる

Posted at

Cloudflareについては、これまで業務で関わることがなくノータッチできてしまいました。さすがに大体どういうものかは一般教養として知っておかないとまずいと思って調べたときのメモです。

CDNではなく、エッジコンピューティング環境としてのCloudflareにフォーカスしています。

Cloudflare Workers

エッジで動作するJavaScriptのランタイム環境です。コンセプトはAWSのLambda@Edgeに似ていると思います。

CloudflareにはFreeプランがあり、無料で試用できます。

Hono + Cloudflare WorkersでWeb APIを作ってみる

最初にCloudflareでアカウントを作成します。

Honoのチュートリアルに従って、Cloudflare Workers用のHonoプロジェクトを作成します。

npm create hono@latest my-app
cd my-app
npm install

src/index.tsを編集して、/にHTTP GETでアクセスした時にHelloメッセージを応答するようにします。

import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.text('Hello Hono!')
})

export default app

まずはローカル環境で実行します。npm run devを実行することで、Cloudflare Workersの開発用ツールであるwranglerが動いて、ローカルサーバで動作確認ができます。ブラウザからhttp://localhost:8787にアクセスするとHello Hono!メッセージが表示されます。

次にCloudflare上のデプロイします。npm run deployでデプロイができます。初めてのデプロイの時には、ブラウザが起動し、Cloudflareへのログインが求められます。

CloudflareのDashboardページでWorkers & Pagesを選択すると、my-appがデプロイできていることが確認できます。

workers_entry.png

ブラウザからhttps://my-app.<Cloudflareのアカウント名>.workers.dev/にアクセスすることで、デプロイしたWorkerが動作していることを確認できます。

KV

Cloudflare Workersから利用できるサーバレスなKey-Valueストアサービスです。

KVはCloudflareのFreeプランで利用可能です。

Hono + Cloudflare WorkersからKVを使ってみる

wranglerコマンドを利用してKVに新たな名前空間を作ります。

npx wrangler kv:namespace create "MY_KV"
npx wrangler kv:namespace create --preview "MY_KV"

CloudflareのDashboardを見て、確かにKVに指定した名前空間ができていることを確認します。

kv_entry.png

Honoのプロジェクトで、wrangler.tomlにKVのBinding情報を追記します。
idとpreview_idには、Dashboardで書くにしたidとpreview_idを設定します。

name = "my-app"
main = "src/index.ts"
compatibility_date = "2024-12-28"

kv_namespaces = [
    { binding = "MY_KV", id = "XXXXX", preview_id = "XXXXX" }
]

index.tsを下記のように変更します。

import { Hono } from 'hono'
import {KVNamespace} from '@cloudflare/workers-types'

type Bindings = {
  MY_KV: KVNamespace
}

const app = new Hono<{Bindings: Bindings}>()

app.post('/posts', async (c) => {
  const id = Math.random().toString(36).substring(7);
  await c.env.MY_KV.put(id, `This is an article of ${id}`);
  return c.json({
    id: id
  }, 201);
});

app.get('/posts/:id', async (c) => {
  const id = c.req.param('id');
  const value = await c.env.MY_KV.get(id);
  return c.json({
    id: id,
    article: value
  }, 200);
});

app.get('/', (c) => {
  return c.text('Hello Hono!')
})

npm run devでローカル実行して、curlコマンドでPOSTしてGETしてみます。

% curl -X POST http://localhost:8787/posts
{"id":"p6ypkm"}
% curl http://localhost:8787/posts/p6ypkm
{"id":"p6ypkm","article":"This is an article of p6ypkm"}%        

npm run deployでデプロイして、同様にcurlコマンドで確認します。
KVを使ったアプリがデプロイできていることがわかります。

% curl -X POST http://my-app.<Cloudflareのアカウント名>.workers.dev/posts
{"id":"14k6dt"}                    
% curl http://my-app.<Cloudflareのアカウント名>.workers.dev/posts/14k6dt 
{"id":"14k6dt","article":"This is an article of 14k6dt"}

CloudflareのDashboardからKVにエントリが追加されていることを確認できます。

kv_record.png

D1

Cloudflare Workersから利用できるサーバレスな分散SQL DBサービスです。組み込みDBであるSQLiteがベースになっています。

D1はCloudflareのFreeプランで利用可能です。

Hono + Cloudflare WorkersからD1を使ってみる

wranglerコマンドを利用してデータベースを新規作成します。

% npx wrangler d1 create my-app-db

テーブルを作ります。ローカルとリモートに作ります。リモートに作る場合は--remoteオプションをつけます。

npx wrangler d1 execute my-app-db --local --command='CREATE TABLE Users(UserID INT, FirstName TEXT, LastName TEXT)'
npx wrangler d1 execute my-app-db --remote --command='CREATE TABLE Users(UserID INT, FirstName TEXT, LastName TEXT)'

Cloudflare Dashboardでテーブルが作成できたことを確認します。

d1.png

Honoのプロジェクトで、wrangler.tomlにKVのBinding情報を追記します。
database_idはwranglerコマンドでデータベースを作成した時に出力された値を設定します。

d1_databases = [
    { binding = "MY_DB", database_name = "my-app-db", database_id = "xxxx" }
]

index.tsに下記のコードを追加します。

import { Hono } from 'hono'
import {KVNamespace, D1Database} from '@cloudflare/workers-types'

type Bindings = {
  MY_KV: KVNamespace
  MY_DB: D1Database
}

type UserInfo = {
  firstName: string
  lastName: string
}

const app = new Hono<{Bindings: Bindings}>()

app.post('/users', async (c) => {
  const userInfo: UserInfo = await c.req.json();
  const id = Math.random().toString(36).substring(7);
  console.log(userInfo);
  await c.env.MY_DB.prepare("INSERT INTO Users (UserID, FirstName, LastName) VALUES (?, ?, ?)").bind(id, userInfo.firstName, userInfo.lastName).run();
  return c.json({
    id: id
  }, 201);
});

app.get('/users/:id', async (c) => {
  const id = c.req.param('id');
  const { results } = await c.env.MY_DB.prepare("SELECT * FROM Users WHERE UserID = ?").bind(id).all();
  if(results.length > 0){
    return c.json({
      id: id,
      firstName: results[0].FirstName,
      lastName: results[0].LastName
    }, 200);
  }else{
    return c.json({}, 404);
  }
});

npm run devでローカル実行して、curlコマンドでPOSTしてGETしてみます。

% curl -X POST -H "Content-Type: application/json" -d  '{"firstName":"Nancy","lastName":"Brown"}' http://localhost:8787/users
{"id":"g2j7wq"}
% curl http://localhost:8787/users/g2j7wq
{"id":"g2j7wq","firstName":"Nancy","lastName":"Brown"}

npm run deployでデプロイして、同様にcurlコマンドで確認します。
KVを使ったアプリがデプロイできていることがわかります。

% curl -X POST -H "Content-Type: application/json" -d  '{"firstName":"Nancy","lastName":"Brown"}' https://my-app.<Cloudflareのアカウント名>.workers.dev/users
{"id":"z6hh6i"}
% curl https://my-app.<Cloudflareのアカウント名>.workers.dev/users/z6hh6i                       
{"id":"z6hh6i","firstName":"Nancy","lastName":"Brown"}

CloudflareのDashboardからKVにエントリが追加されていることを確認できます。

d1_record.png

R2

Cloudflare Workersから利用できるオブジェクトストレージです。

R2はCloudflareのFreeプラインでは利用ができません。

後処理

動作確認が終わったらworkerを削除しておきます。

npx wrangler delete my-app

まとめ

Honoを使って実装したWorkerから、KVやD1が簡単に利用できました。

JavaScriptの実行環境に加えて、オブジェクトストレージ、キーバーリューストア、SQLデータベースが揃っているので、小規模なWebアプリケーションであれば、問題なく実現ができそうです。

コストが安いので、個人開発の場合は、AWSよりも先にCloudflareを検討した方が、良いかもしれません。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?