Open3
Hono RPC & Cloudfrale Pages & Functions & D1 備忘録
完成品
パッケージのバージョン一覧
package.json
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20230228.0",
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"@vitejs/plugin-react-swc": "^3.0.0",
"better-sqlite3": "^8.0.1",
"hono": "^3.0.3",
"typescript": "^4.9.3",
"vite": "^4.1.0",
"wrangler": "^2.12.0"
}
viteで環境構築
npm create vite@latest
パッケージの追加、npm scriptの編集
npm i -D @cloudflare/workers-types hono wrangler
package.json
"scripts": {
- "dev": "vite",
+ "dev": "wrangler pages dev --compatibility-date=2023-03-01 --d1=DB --persist -- vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
https://zenn.dev/yusukebe/articles/c86b8bd8d47a53 を参考にした
wrangerの引数については公式を参照
- https://developers.cloudflare.com/workers/wrangler/commands
-
--d1=DB
D1のbindingの設定 -
--persist
ローカルモードの永続化(.wranger/state/d1
を参照する)
d1を作成する
wrangler d1 create todo-demo
wrangler.toml
が作成される。
[[ d1_databases ]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "todo-demo"
database_id = "xxx"
一度 npm run dev
を実行しするとローカルのd1が作成される。
# /.wrangler/state/d1/DB.sqlite3が作成される。
npm run dev
ローカルのDBにテーブルの作成とデータの投入を行う。
todo-schema.sql
DROP TABLE IF EXISTS todos;
CREATE TABLE Todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL
)
add-todo.sql
INSERT INTO todos (title) VALUES
('Task 1'),
('Task 2'),
('Task 3'),
('Task 4'),
('Task 5'),
('Task 6'),
('Task 7'),
('Task 8'),
('Task 9'),
('Task 10');
# テーブル作成
wrangler d1 execute todo-demo --file=./sql/todo-schema.sql --local
# データ投入
wrangler d1 execute todo-demo --file=./sql/add-todo.sql --local
ローカルで動作確認する
npm run dev
で起動する。
[proxy]:
VITE v4.1.4 ready in 170 ms
[proxy]: ➜ Local: http://localhost:5173/
➜ Network: use --host to expose
Automatically determined the proxy port to be 5173.
リバースプロキシにより http://127.0.0.1:5173/api/todos
にAPIが生えると思っていたが、workerデフォルトの 8788
からになってた。
そのためdevはcorsを設定する。
App.tsx
import { useEffect, useState } from 'react';
import './App.css';
import { hc } from 'hono/client';
import type { AppType, TodoResponse } from '../functions/api/[[route]]';
function App() {
const [todos, setTodos] = useState<TodoResponse[]>([]);
useEffect(() => {
async function getTodos() {
const url = import.meta.env.DEV ? 'http://localhost:8788/api' : 'api';
const client = hc<AppType>(url);
const res = await client.todos.$get();
const json = await res.json();
return json;
}
getTodos().then((todos) => {
console.warn(todos);
setTodos(todos);
});
}, []);
return (
<div className='App'>
{todos.map((todo) => {
return (
<p key={todo.id}>
id: {todo.id} title: {todo.title}
</p>
);
})}
</div>
);
}
export default App;
functions/api/[[route]].ts
import type { D1Database } from '@cloudflare/workers-types';
import { handle } from 'hono/cloudflare-pages';
import { Hono } from 'hono';
import { cors } from 'hono/cors';
type Bindings = {
DB: D1Database;
};
type Todo = {
title: string;
};
export type TodoResponse = Todo & {
id: number;
};
const app = new Hono<{ Bindings: Bindings }>();
app.use(
'*',
cors({
origin: '*',
allowHeaders: ['Content-Type', 'Authorization'],
allowMethods: ['POST', 'GET', 'OPTIONS'],
exposeHeaders: ['Content-Length'],
maxAge: 600,
credentials: true,
})
);
const route = app.get('/todos', async (c) => {
const { results } = await c.env.DB.prepare(
'SELECT * FROM todos;'
).all<TodoResponse>();
return c.jsonT(results || []);
});
export type AppType = typeof route;
export const onRequest = handle(app, '/api');
Todoが10件表示されればOK
デプロイする
deploy用のスクリプトを追加する
json
"scripts": {
"dev": "wrangler pages dev --persist --d1=DB -- vite",
"build": "tsc && vite build",
+ "preview": "vite preview",
+ "deploy": "npm run build && wrangler pages publish pages",
}
テーブル作成とデータ投入をする
# テーブル作成
wrangler d1 execute todo-demo --file=./sql/todo-schema.sql
# データ投入
wrangler d1 execute todo-demo --file=./sql/add-todo.sql
一度デプロイする
npm run deploy
デプロイ後、サイトにアクセスしてみる。
おそらく500エラーになっており、原因はd1とのバインディングをしてないため。
Cloudflare Pagesの設定タブに D1データベースバインディング
の項目がある。
変数名を DB
, データベースを作成したものにして設定する。
設定後、再度デプロイし500エラーが解消されればOK