はじめに
今回から新シリーズとして、今最も注目されているモダンなWeb開発スタック「React × Cloudflare Workers × Hono」を使ったサーバーレスWebアプリ(ToDoアプリ)の開発に挑戦します!
「サーバーレス」や「API開発」と聞くと難しく感じられるかもしれませんが、Webフレームワークの Hono を使うと、驚くほどシンプルかつ直感的にバックエンド(API)を構築できます。
第1弾の今回は、まず環境構築からスタートし、Honoを使ってToDoの追加・表示・更新・削除(CRUD)ができるWeb APIを爆速で作っていきます!
1. 今回作る構成とロードマップ
本シリーズでは最終的に、以下のフルスタック構成で世界中に無料公開(デプロイ)できるアプリを目指します。
[ フロントエンド (React) ]
│
fetch通信 (JSON)
│
▼
[ バックエンド (Hono / Cloudflare Workers) ] 👈 ★今回はここを作成!
│
▼
[ データベース (Cloudflare D1) ] 👈 ※第2弾で連携!
全体のロードマップ
- 第1弾(今回):HonoでバックエンドAPI構築(インメモリで速習)
- 第2弾: Cloudflare D1(DB)を連携してデータを永続化する
- 第3弾: React (Vite) でフロントエンド画面を作ってAPIと接続する
- 第4弾: Cloudflare Pages / Workers へ世界一括デプロイ!
2. 環境構築(Honoプロジェクトの作成)
さっそく、Cloudflare Workers + Hono のプロジェクトを立ち上げましょう。 ターミナル(またはコマンドプロンプト)を開き、以下のコマンドを実行します。
npm create hono@latest my-todo-apiセットアップの質問には以下のように答えて進めます:
- Which template do you want to use?: cloudflare-workers を選択
- Do you want to use TypeScript?: no(※JavaScriptでシンプルに進める場合。TypeScriptでもOK)
- Do you want to install project dependencies?: Yes
プロジェクトが作成されたら、作成されたディレクトリに移動します。
cd my-todo-api3. CRUD APIを実装しよう!
それでは src/index.js(または src/index.ts)を開き、コードを以下のように書き換えます。
今回は学習のハードルを下げるため、データはメモリ上の配列(todos)で管理します。
import { Hono } from 'hono'
import { cors } from 'hono/cors'
const app = new Hono()
// 1. フロントエンド(React)からの接続を許可するCORS設定
app.use('/api/*', cors())
// 2. テスト用の初期データ(インメモリ配列)
let todos = [
{ id: '1', title: '部屋の掃除をする', completed: false },
{ id: '2', title: 'Reactの勉強をする', completed: true },
]
// --------------------------------------------------
// READ: ToDo一覧の取得
// --------------------------------------------------
app.get('/api/todos', (c) => {
return c.json(todos)
})
// --------------------------------------------------
// CREATE: 新しいToDoの追加
// --------------------------------------------------
app.post('/api/todos', async (c) => {
const body = await c.req.json()
// タイトルが空の場合はエラー(400)を返す
if (!body.title || !body.title.trim()) {
return c.json({ error: 'タイトルは必須です' }, 400)
}
const newTodo = {
id: Date.now().toString(), // 簡易的なユニークID
title: body.title,
completed: false,
}
todos.push(newTodo)
return c.json(newTodo, 201) // 201 Created
})
// --------------------------------------------------
// UPDATE: ToDoの更新(完了フラグの切替など)
// --------------------------------------------------
app.put('/api/todos/:id', async (c) => {
const id = c.req.param('id')
const body = await c.req.json()
// 該当するToDoを探して更新する
let updatedTodo = null
todos = todos.map((todo) => {
if (todo.id === id) {
updatedTodo = { ...todo, ...body }
return updatedTodo
}
return todo
})
if (!updatedTodo) {
return c.json({ error: '該当するToDoが見つかりません' }, 404)
}
return c.json(updatedTodo)
})
// --------------------------------------------------
// DELETE: ToDoの削除
// --------------------------------------------------
app.delete('/api/todos/:id', (c) => {
const id = c.req.param('id')
// 指定されたID以外のToDoを残す(フィルタリング)
todos = todos.filter((todo) => todo.id !== id)
return c.json({ message: '削除が完了しました' })
})
export default app4. ここがスゴイ!Honoのポイント解説
わずか60行程度のコードですが、Web APIに必要な処理がすべて詰まっています!
① c.json() で一発レスポンス
Expressなど従来のフレームワークだとヘッダー指定が必要だったJSONレスポンスも、Honoなら return c.json(データ) と書くだけで自動的に Content-Type: application/json を付与して返してくれます。
② 直感的なパラメータ取得
- URL内のID(/api/todos/:id):c.req.param(‘id’) で取得
- POSTやPUTのリクエストボディ(JSON):await c.req.json() で取得
③ CORSミドルウェアが標準用意されている
将来的にReact(ポート3000など)からAPI(ポート8787など)を呼び出す際、ブラウザのセキュリティ制限(CORSエラー)にかかります。Honoなら app.use(‘/api/*’, cors()) を1行書くだけで解決できます。
5. ローカルサーバーを起動して動かしてみよう!
作成したAPIをローカル環境で動かしてみましょう。以下のコマンドを実行します。
npm run devターミナルに http://localhost:8787 のようなURLが表示されたら準備完了です!
ブラウザで http://localhost:8787/api/todos にアクセスしてみてください。 以下のようなJSONデータが表示されれば、GET(一覧取得)APIの作成成功です!
[
{ "id": "1", "title": "部屋の掃除をする", "completed": false },
{ "id": "2", "title": "Reactの勉強をする", "completed": true }
]6. ターミナルコマンドからCRUD操作をしてみよう
簡単にターミナルコマンドを使ってAPI操作をしてみましょう。
mac linuxのコマンドは以下の curl コマンドで、windowsの方はさらに下で解説するInvoke-RestMethodコマンドで行います。
【追加 (CREATE)】新しいToDoを追加する (POST)
-X POST でリクエストを送信し、-H で「JSONデータを送りますよ」と伝え、-d に送信したいJSONデータを渡します。
curl -X POST http://localhost:8787/api/todos \
-H "Content-Type: application/json" \
-d '{"title": "ターミナルからテスト追加"}'実行して以下のようにID付きのJSONが返ってくれば成功です!
{"id":"1712345678900","title":"ターミナルからテスト追加","completed":false}【削除 (DELETE)】指定したIDのToDoを削除する (DELETE)
-X DELETE を指定し、URLの末尾に削除したいToDoの id を付けて実行します。
例えば、初期データにある id: “1”(部屋の掃除をする)を削除する場合はこちらです。
curl -X DELETE http://localhost:8787/api/todos/1成功した時の返り値(レスポンス)はこちら
{"message":"削除が完了しました"}【更新 (UPDATE)】完了フラグを true に切り替える (PUT)
例えば id: “2” のToDoを「完了(completed: true)」に変更する場合:
curl -X PUT http://localhost:8787/api/todos/2 \
-H "Content-Type: application/json" \
-d '{"completed": true}'📝 PowerShell(Windows標準)を使う場合の注意点
Windowsの標準 PowerShell をお使いの場合、curl は内部で別のコマンド(Invoke-WebRequest)の別名になっていることがあり、上記の書き方だとエラーになる場合があります。
PowerShellで実行する場合は、以下のように Invoke-RestMethod(インボーク・レスト・メソッド)で行うと確実に動作します。
PowerShell用コマンド例(POST追加)
Invoke-RestMethod(インボーク・レスト・メソッド)は、Windowsの標準ターミナル(PowerShell)に最初から組み込まれている「Web APIと通信するための標準コマンド(コマンドレット)」です。
LinuxやMacでよく使われる curl のPowerShell版のような存在で、WebサーバーやWeb APIに対してデータの要求(GET)や送信(POST/PUT/DELETE)を行うことができます。
Invoke-RestMethod -Uri "http://localhost:8787/api/todos" -Method Post -ContentType "application/json" -Body '{"title":"PowerShellから追加"}'
PowerShell用コマンド例(DELETE削除)
Invoke-RestMethod -Uri "http://localhost:8787/api/todos/1" -Method Deleteまとめと次回予告
今回は Hono を使って、ToDoアプリに必要な CRUD (Create / Read / Update / Delete) のAPI基盤を作成しました。
Honoのシンプルさと、Cloudflare Workersの起動速度の速さを体感していただけたのではないでしょうか?
ただし、現在の実装だと「ローカルサーバーを再起動すると、追加したToDoが消えてしまう(インメモリデータのため)」 という問題があります。
そこで次回・第2弾では、Cloudflareが提供するサーバーレス分散データベース 「Cloudflare D1」 を導入し、データをデータベースへ永久に保存できるようにアップデートしていきます!お楽しみに!

コメント