第287章:D1 (エッジデータベース) 入門
この章は「Cloudflare Workers(Hono)から、D1(SQLiteベースのDB)を使ってデータを保存&取得する」入口だよ〜!😊 D1 は Cloudflare の マネージドなサーバレスSQL(SQLite互換)DB で、Workers から バインディング(env)経由で触れるのが基本スタイル✨ (Cloudflare Docs)
まずD1ってなに?ざっくり理解しよ〜 🧠✨
- D1 = SQLiteのSQL感覚で使える、CloudflareのDB
- Workers / Pages から ほぼ直結でクエリできる(バインディングで
env.DBみたいに触る) (Cloudflare Docs) - **Time Travel(過去に戻す)**もあって、最長30日・分単位で復元できる(強い…!)🕰️ (Cloudflare Docs)
全体のつながり(図解)🗺️✨

今日作るもの(ミニ)🎯✨
**「メモAPI」**を作って、D1 に保存するよ📌
GET /api/notes:メモ一覧を返すPOST /api/notes:メモを追加する
1) D1データベースを作る 🛠️✨(Wrangler)
PowerShell(またはターミナル)でOK!
✅ 1-1. Cloudflare にログイン
npx wrangler login
✅ 1-2. D1 を作成
例:edge-notes-db という名前で作るよ🌸
npx wrangler@latest d1 create edge-notes-db
成功すると、database_id が表示されるはず!それを後で使うよ📝
(この流れは公式の Getting started にもあるよ) (Cloudflare Docs)
2) Worker に D1 を “バインド” する(設定ファイル)🔗✨
最近は wrangler.jsonc 推し(新機能がJSONでしか使えないこともある)なので、ここも wrangler.jsonc で行くね😊 (Cloudflare Docs)
✅ wrangler.jsonc(例)
database_id はさっきのを貼ってね!
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "edge-notes",
"main": "src/index.ts",
"compatibility_date": "2025-12-28",
"d1_databases": [
{
"binding": "DB",
"database_name": "edge-notes-db",
"database_id": "ここにあなたのdatabase_id"
}
]
}
これで Worker から env.DB(Honoなら c.env.DB)として使えるよ! (Cloudflare Docs)
3) マイグレーションでテーブルを作る 🧱✨
D1 は “SQLファイルで差分管理” が超おすすめ! (チームでも未来の自分でも助かるやつ🫶)
✅ 3-1. マイグレーション作成
npx wrangler d1 migrations create edge-notes-db init
migrations/ に SQL ファイルができるので、こんな感じにする👇
-- migrations/0001_init.sql
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
body TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_notes_created_at ON notes(created_at);
✅ 3-2. ローカルに反映(開発用)
npx wrangler d1 migrations apply edge-notes-db --local
✅ 3-3. 本番(リモート)に反映(必要なタイミングで)
npx wrangler d1 migrations apply edge-notes-db --remote
--local / --remote が公式で用意されてるよ🧠 (Cloudflare Docs)
4) Hono から D1 を叩く(API実装)⚡🗃️
✅ ポイント:SQLは prepare() + bind() が基本だよ🛡️
これ、SQLインジェクション対策にもなるし、公式も “推奨” してる✨ (Cloudflare Docs)
src/index.ts(Workers + Hono)
import { Hono } from "hono";
type Bindings = {
DB: D1Database;
};
const app = new Hono<{ Bindings: Bindings }>();
app.get("/api/notes", async (c) => {
const { results } = await c.env.DB.prepare(
"SELECT id, title, body, created_at FROM notes ORDER BY id DESC LIMIT 50"
).all();
return c.json(results);
});
app.post("/api/notes", async (c) => {
const data = await c.req.json<{ title: string; body: string }>();
if (!data.title?.trim() || !data.body?.trim()) {
return c.json({ message: "title と body は必須だよ〜🥺" }, 400);
}
const result = await c.env.DB.prepare(
"INSERT INTO notes (title, body) VALUES (?, ?)"
)
.bind(data.title, data.body)
.run();
return c.json({ id: result.meta.last_row_id });
});
export default app;
Hono では c.env に bindings が来るので、c.env.DB でD1に触れるよ〜! (Cloudflare Docs)
5) ローカルで動かす(D1込みで動くよ!)🏃♀️💨
npx wrangler dev
いまの Wrangler は wrangler dev がローカルモード標準で、D1 もローカルの別DBとして動くよ✨
しかもローカルは 本番データに勝手に繋がらないから安心😊 (Cloudflare Docs)
🌟注意:ローカルDBは “基本、保持される”
Wrangler v3+ は wrangler dev を止めても データが残るのが普通だよ!
まっさらで試したいなら DROP TABLE ... などで消してから作り直す感じ👌 (Cloudflare Docs)
6) ちょいテスト(SQL直打ち)🔍✨
ローカルに1件入れてみよ〜!
npx wrangler d1 execute edge-notes-db --local --command "INSERT INTO notes (title, body) VALUES ('hello', 'D1たのしい!')"
一覧も見てみる👇
npx wrangler d1 execute edge-notes-db --local --command "SELECT * FROM notes ORDER BY id DESC"
d1 execute にも --local/--remote があるよ〜! (Cloudflare Docs)
React側から呼ぶイメージ(ミニ)📱✨
もし React(Vite)側が別ポートなら、開発中はプロキシが楽ちん😺
vite.config.ts(例)
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
server: {
proxy: {
"/api": "http://127.0.0.1:8787",
},
},
});
これで React から fetch("/api/notes") でOKになりやすいよ🙌
リクエストの流れ(図解)📨✨
ちょい先取り(すごいやつ)🌍⚡
D1 には **Global Read Replication(読み取りレプリカ)**があって、うまく使うと世界中で読み込みが速くなる方向があるよ〜! さらに “セッション” を使うと 同じユーザーの操作で整合性(read my own writes みたいな性質)を保つ設計もある✨ (The Cloudflare Blog)
(ここは第288章以降の「未来」と繋がるゾーンだね😳)
まとめ 🎀
- D1 は SQLite互換のサーバレスDBで、Workers と相性バツグン🗃️⚡ (Cloudflare Docs)
- 設定は バインディング(DB) → コードは
c.env.DBで触る😊 (Cloudflare Docs) - クエリは prepare + bind が基本で安全🛡️ (Cloudflare Docs)
- ローカル開発は
wrangler devでOK(ローカルDBで動く)🙌 (Cloudflare Docs)
おまけ課題(やると強い💪✨)
- ✅
DELETE /api/notes/:idを追加して「削除」できるようにする🧹 - ✅
titleを部分一致検索するGET /api/notes?query=...を作る🔎 - ✅
created_atの表示を “いい感じの日時” に整える⏰
必要なら、この章の続きとして「React側のUI(一覧+追加フォーム)まで完成」も、まるっと作るよ〜😊💖