Cloudflare Pages + D1 免费动态网站开发
在这篇文章中,我们将从创建第一个 D1 数据库开始,一步步构建一个由 Cloudflare Pages 驱动前端D1 数据库提供后端支持的全栈应用。我们将详细解析 wrangler.toml
的每一项配置,阐明本地开发和云端部署的核心命令,并揭示那些导致“表不存在”或“部署失败”等常见问题的根本原因。
性能对比总结表
特性 | Cloudflare Pages + D1 | Go + Gin (传统 VPS) | 纯静态网站 |
---|---|---|---|
访问速度 (TTFB) | 静态部分极快,动态部分快 | 区域内快,全球慢 | 极致快 |
数据延迟 (DB Query) | 好,但受限于区域 | 区域内极好 | 不适用 |
可伸缩性/并发 | 极高 (自动弹性伸缩) | 有限 (需手动扩容) | 极高 (CDN 天然优势) |
冷启动 | 有 (但极短) | 无 (进程常驻) | 无 |
运维复杂度 | 极低 (Serverless) | 高 (需管理服务器系统安全) | 极低 |
开发体验 | 现代,前后端分离 | 成熟,一体化或分离均可 | 简单,但受限 |
成本 | 起步极低,按量付费 | 固定月费,随流量增长 | 极低 |
核心理念:理解两个独立的环境
在开始之前,最重要的一点是理解:你的本地开发环境和你部署到的 Cloudflare 云端环境是完全隔离的。
- 本地环境:所有文件数据库 (
.wrangler
目录下的.sqlite
文件) 都存储在你的电脑上。 - 云端环境:代码和静态文件部署在全球网络上,连接的是一个完全独立的在云端的 D1 数据库。
你在本地对数据库做的任何修改(比如创建表),都不会自动同步到云端,反之亦然。这是所有问题的根源。
以下是 D1 的免费额度:
功能 (Feature) | 免费额度 | 说明 |
---|---|---|
数据库总数 (Total Databases) | 10 个 | 你的 Cloudflare 账户可以创建的数据库实例总数。 |
数据库存储空间 (Database Storage) | 5 GB | 你所有 D1 数据库占用的磁盘空间总和。 |
每天读取行数 (Rows Read per Month) | 500 万次 | 所有 SELECT 等读操作访问的行数总和。 |
每天写入行数 (Rows Written per Month) | 10 万次 | 所有 INSERT UPDATE DELETE 等写操作影响的行数总和。 |
第零步:创建你的 D1 数据库
在编写任何代码之前,我们首先需要在 Cloudflare 上拥有一个 D1 数据库。这可以通过 Wrangler CLI 方便地完成。
-
打开你的项目终端。
-
运行创建命令:
#安装wrangler npm install wrangler
# 语法: wrangler d1 create <DATABASE_NAME> wrangler d1 create blog
-
保存输出结果:命令执行成功后,Wrangler 会返回一段
wrangler.toml
配置代码。这段代码至关重要,请立即将它复制下来。它看起来会是这样:
[[d1_databases]] binding = "DB" # 这个名字可以自定义,但建议保持 "DB" database_name = "blog" database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
这里的
database_id
是 Cloudflare 为你的数据库生成的唯一标识符。
现在,你已经在云端拥有了一个名为 blog
的空数据库。接下来,我们将在项目配置中引用它。
第一步:奠定基石 - wrangler.toml
配置详解
wrangler.toml
是你项目的指挥中心。在项目根目录下创建(或修改)这个文件,并将我们刚才获得的配置粘贴进去,然后补充其他必要信息。
# wrangler.toml
# 1. 基本信息
# 你的 Cloudflare Pages 项目名称,会显示在仪表盘上
name = "my-d1-blog"
# Pages Functions 的入口文件,对于中间件模式,通常是这个
main = "functions/_middleware.js"
# 2. 兼容性设置
# 确保你的代码在特定版本的 Workers 运行时上行为一致
compatibility_date = "2024-03-01"
# 3. 账户信息
# 你的 Cloudflare 账户 ID
account_id = "YOUR_ACCOUNT_ID" # 替换成你自己的 Account ID
# 4. Pages 构建配置
[pages_build]
# Cloudflare 构建项目时运行的命令,用于生成静态文件
build = "go run generate_static.go"
# 构建命令生成的静态文件的输出目录
build_output_dir = "dist"
# 5. D1 数据库绑定(将刚才创建数据库时复制的内容粘贴到这里,并进行补充)
[[d1_databases]]
# 绑定变量名:在你的 Function 代码中,通过 env.DB 访问数据库
binding = "DB"
# 数据库名称:在 Cloudflare 仪表盘中显示的名称
database_name = "blog"
# 数据库的唯一ID (从创建命令的输出中获取)
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # 替换成你自己的 Database ID
# 【关键】预览/本地数据库ID:确保本地开发时也使用这个ID对应的数据库
# 直接复制上面的 database_id 即可
preview_database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # 替换成你自己的 Database ID
# 数据库迁移文件(SQL schema)所在的目录
migrations_dir = "d1/migrations"
配置项深度解析:
-
account_id
如何获取?- 登录 Cloudflare 仪表盘。
- 在主页的右侧边栏,找到并点击 "Workers & Pages"。
- 在 "Workers & Pages" 概览页面的右侧,你会看到你的 账户 ID (Account ID)。直接点击复制即可。
-
[[d1_databases]]
为何如此重要?
这部分就是你项目的“地址簿”,它告诉 Wrangler:binding = "DB"
:在代码里,请创建一个名为DB
的变量。database_name = "blog"
和database_id = "..."
:这个DB
变量应该连接到名为blog
ID 为...
的那个云端 D1 数据库。preview_database_id = "..."
:这是解决本地开发问题的关键! 它明确告诉 Wrangler,当运行本地开发服务器 (wrangler pages dev
) 时,也应该使用与这个 ID 关联的持久化本地数据库文件,而不是创建一个临时的内存数据库。migrations_dir = "..."
:当运行迁移命令时,请到这个目录里寻找 SQL 文件。
第二步:本地开发 - 正确的命令与错误的陷阱
本地开发流程分为两步:准备数据库和启动服务。
1. 准备本地数据库 (wrangler d1 migrations apply
)
这个命令用来在你的本地数据库中创建表索引等结构。
# --local 标志是关键,表示在本地操作
wrangler d1 migrations apply blog --local
Migrations to be applied:
┌──────────────────────────┐
│ name │
├──────────────────────────┤
│ 0001_create_articles.sql │
└──────────────────────────┘
√ About to apply 1 migration(s)
Your database may not be available to serve requests during the migration, continue? ... yes
🌀 Executing on local database blog (3d8df471-0e35-457a-a43e-915fe6e0a920) from .wrangler\state\v3\d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
🚣 5 commands executed successfully.
┌──────────────────────────┬────────┐
│ name │ status │
├──────────────────────────┼────────┤
│ 0001_create_articles.sql │ ✅ │
└──────────────────────────┴────────┘
它做了什么?
- 读取
wrangler.toml
,找到database_name = "blog"
的配置。 - 在你的项目下找到
.wrangler/state/v3/d1
目录,并定位到与preview_database_id
匹配的那个.sqlite
文件。如果不存在,则会创建。 - 读取
migrations_dir
指定目录下的所有 SQL 文件。 - 在那个
.sqlite
文件中执行这些 SQL 语句,创建你的表。
2. 启动本地开发服务 (wrangler pages dev
)
现在,启动你的本地服务器来预览整个应用。
✅ 正确的命令:
wrangler pages dev dist
它做了什么?
- 读取
wrangler.toml
。 - 看到
[pages_build]
配置,它会自动运行go run generate_static.go
来确保dist
目录是最新的。 - 启动一个本地服务器,托管
dist
目录的静态文件。 - 看到
[[d1_databases]]
配置,它会自动将env.DB
绑定到由preview_database_id
确定的同一个本地数据库文件。 - 你的应用现在可以愉快地读写那个已经创建好表的本地数据库了。
❌ 错误的陷阱:
# 这是一个非常常见的错误命令!
wrangler pages dev dist --d1=DB
它做了什么?
--d1=DB
这个标志是一个覆盖指令。它告诉 Wrangler:“忽略 wrangler.toml
里所有关于 D1 的配置!现在,立即为我创建一个全新的空的临时的只存在于内存中的 D1 数据库,并把它绑定给 DB
变量。”
后果:你的应用连接到了一个空数据库,当它执行 SELECT * FROM articles
时,自然就会抛出 D1_ERROR: no such table: articles
的错误。
第三步:部署到云端 - 连接真实世界
本地开发完美后,就可以部署了。记住,云端是一个全新的空的环境。
1. 准备云端数据库 (wrangler d1 migrations apply --remote
)
你需要把你的数据库表结构应用到云端的真实的 D1 数据库上。
# --remote 标志是关键,表示在云端操作
wrangler d1 migrations apply blog --remote
它做了什么?
这个命令和本地版本类似,但它会使用你的 Cloudflare API 凭据,连接到云端那个真实的 blog
数据库,并在其中执行迁移 SQL。这是一个一次性的设置步骤(除非将来你需要修改表结构)。
2. 在 Cloudflare 仪表盘上确认绑定
这是最容易被忽略,也最致命的一步。你需要确保你的 Pages 项目被授权访问 D1 数据库。
- 登录 Cloudflare 仪表盘 -> Workers & Pages。
- 点击你的 Pages 项目 (例如
my-d1-blog
),而不是 D1 数据库。 - 进入 "设置" (Settings) -> "函数" (Functions)。
- 向下滚动到 "D1 数据库绑定" (D1 database bindings)。
- 确认或添加一条绑定:
- 变量名称 (Variable name):
DB
- D1 数据库 (D1 database):
blog
- 变量名称 (Variable name):
- 点击 "保存"。
这一步在 wrangler.toml
和你的云端项目之间建立了最终的连接。
3. 部署应用
现在万事俱备,只需部署即可。
-
通过 Git (推荐):如果你连接了 Git 仓库,只需
git push
即可。Cloudflare 会自动构建和部署。 -
通过 Wrangler CLI:
wrangler pages deploy dist
Your Worker has access to the following bindings:
Binding Resource Mode
env.DB (3d8df471-0e35-457a-a43e-915fe6e0a920) D1 Database local╭──────────────────────────────────────────────────────────────────────╮
│ [b] open a browser [d] open devtools [c] clear console [x] to exit │
╰──────────────────────────────────────────────────────────────────────╯
⎔ Starting local server...
[wrangler:info] Ready on http://127.0.0.1:8788
备份d1数据库
查看数据库
wrangler d1 list
⛅️ wrangler 4.27.0
uuid name created_at version num_tables file_size 3d8df471-XXX blog 2025-08-04T07:07:40.758Z production 0 28672 89570ac6-XXX diary 2025-05-23T09:37:59.459Z production 0 12288
备份(需要在wrangler.toml同目录下)
wrangler d1 export blog --output backup.sql
🌀 Exporting local database blog (3d8df471-0e35-457a-a43e-915fe6e0a920) from .wrangler\state\v3\d1:
🌀 To export your remote database, add a --remote flag to your wrangler command.
🌀 Exporting SQL to backup.sql...
Done!
结论与排错清单
如果再遇到问题,请对照以下清单进行排查:
-
wrangler.toml
是否正确?account_id
和database_id
是否正确填写?- 是否已添加
preview_database_id
?
-
本地开发问题?
- 是否运行了
wrangler d1 migrations apply blog --local
? - 启动命令是否是不带
--d1
标志的wrangler pages dev dist
? - 是否尝试过删除
.wrangler
目录并重新运行迁移?
- 是否运行了
-
云端部署失败?
- 是否运行了
wrangler d1 migrations apply blog --remote
? - 是否在 Pages 项目的设置 -> 函数 中手动检查并确认了 D1 绑定?
- 是否查看了 Cloudflare 仪表盘中的部署日志以获取具体的错误信息?
- 是否运行了
本文作者: 永生
本文链接: https://yys.zone/detail/?id=450
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
评论列表 (0 条评论)