为什么选 Cloudflare Pages
市面上的免费托管不少,但 Pages 有几个实打实的优势。
| 维度 | Cloudflare Pages | Vercel | Netlify | GitHub Pages |
|---|---|---|---|---|
| 费用 | 免费额度充足 | 免费(100GB 流量) | 免费(100GB) | 免费 |
| 全球 CDN | Cloudflare 全网 | 快 | 中 | 节点少 |
| 私有仓库 | 支持 | 支持 | 支持 | 免费版不支持 |
| 商用 / 电商 | 明确允许 | 免费版条款较严 | 视计划而定 | 官方禁止 |
| HTTPS 证书 | 自动签发 | 自动 | 自动 | 需手动 |
| 构建额度 | 充足 | 较严 | 300 分钟/月 | 10 次/小时 |
| AI 原生部署 | 官方 MCP + Skills | 有限 | 有限 | 无 |
关键结论:纯静态站点(HTML / CSS / JS,或框架构建后的产物)非常适合 Pages。部署结果是 https://你的项目名.pages.dev,全球 CDN 加速,HTTPS 自动配好,完全免费。
开始前的准备
两样东西就够:一个 Cloudflare 账号,和一份"已经能本地跑起来"的网站文件。
1. 注册 Cloudflare 账号
访问 dash.cloudflare.com/sign-up,填写邮箱和密码,验证邮箱后进入控制台。
- 选 Free 免费套餐(默认就是这个)
- 不需要绑定信用卡
- 中途会问是否购买域名 / 迁移 DNS,全部跳过即可,纯托管静态站不需要域名也能上线
2. 确认你要上传的是"构建产物"
这是新手最容易踩的坑:Cloudflare 要的不是源码,而是网站最终的文件。也就是说根目录必须有 index.html。
| 你的项目类型 | 该上传哪个目录 | 先执行什么 |
|---|---|---|
| 纯手写 HTML / CSS / JS | 项目根目录 | 无需构建,直接传 |
| Vue / Vite | dist/ | npm run build |
| React(CRA) | build/ | npm run build |
| Next.js(静态导出) | out/ | next build 后设 output: 'export' |
| Astro | dist/ | npm run build |
| Hugo | public/ | hugo |
| uni-app / 微信小程序 (不适用) | 小程序代码不能直接部署到 Pages,需要先转成 H5 | |
# 传之前先在本地双击 index.html 确认能正常显示
my-site/
├── index.html # 必须有,且在第一层
├── about.html
├── css/
│ └── style.css
├── js/
│ └── main.js
└── images/
└── logo.png
# 常见错误:把上一级文件夹拖进去,会导致 404
# 正确做法:进入 my-site 内部,全选所有文件再拖
上传前自检清单:
- 构建输出目录里有
index.html - 本地用
python3 -m http.server 8000能正常打开 - 单文件没超过 25 MiB,文件总数没超(见下方限制表)
- 路径引用都是相对路径(不要写
/Users/你的名字/...这种绝对路径)
3. 拖拽上传的硬性限制
| 上传方式 | 文件数量上限 | 单文件大小上限 | 支持 ZIP |
|---|---|---|---|
| 控制台拖拽 | 1,000 个 | 25 MiB | 支持 |
| Wrangler CLI | 20,000 个 | 25 MiB | 不支持,需先解压 |
先选路线:四种部署方式
不用都学,按你的场景挑一条走完就行。后面每条路线都有完整步骤。
① 拖拽上传
打开控制台,把文件夹拖进去就完事了。适合一次性的小站、演示页面、想快速看到效果的人。
② Git 集成
连上 GitHub / GitLab,之后每次 git push 自动部署,每次 PR 自动生成预览环境。
③ Wrangler CLI
本地一条命令上传,支持自定义分支、CI 自动化,文件数上限更高(20000)。
④ AI 部署
接入 Cloudflare 官方 MCP / Skills,在 AI 编程工具里说一句"帮我部署",它自己完成上传并返回网址。
怎么选?
- 只想试一下 / 交作业 → 路线 ①,拖拽 3 分钟搞定
- 自己维护的项目,要长期迭代 → 路线 ②,之后每个改动自动上线
- 文件多、或要接 CI → 路线 ③
- 平时就用 AI 写代码 → 路线 ④,把部署也交给 AI,你什么都不用改
路线一:拖拽上传
不需要装任何东西,全程鼠标操作。这是验证"我的网站能不能上线"最快的方式。
登录控制台后,从左侧导航进入 Workers & Pages,点 Create application,选择 Pages 标签页,然后点 Get started。
如果看到 Drag and drop your files 选项,说明走对了。
项目名会成为你的默认网址:https://项目名.pages.dev。只能用小写字母、数字、连字符。
起名技巧:名字一旦确定很难改(要删项目重建)。想清楚再填。名字冲突时 Cloudflare 会自动加随机后缀。
把准备好的构建产物文件夹(或它的 ZIP 压缩包)拖进虚线框。注意:拖的是文件夹本身,不是它的父目录。
Desktop → 网站里出现 my-site/index.html → 访问报 404
✓ 正确: 拖了 my-site 文件夹 → 根目录直接就是 index.html上传完成后点 Deploy site,等待 30–60 秒。构建日志会实时显示,成功后自动跳转到你的站点。
怎么更新?在项目页点 Create a new deployment → 选择目标环境(Production 生产 / Preview 预览)→ 重新拖入文件。可以选择新建分支或填已有分支名。
限制提醒:控制台拖拽不支持编译 functions/ 目录(Pages Functions)。如果你有边缘函数,只能用 Wrangler 上传。单个文件超 25 MiB 会标红且无法上传,只能删掉后重新传整个项目。
路线二:Git 集成(自动部署)
连一次 GitHub,之后每次 push 自动上线。这是长期维护项目的正确姿势。
前置条件
- 网站代码已经推送到 GitHub / GitLab 仓库(私有仓库也可以)
- 项目根目录里有
package.json,且scripts.build已配好(纯静态站可跳过)
Workers & Pages → Create application → Connect to Git(或从已有项目进 Settings → Git)。点 Connect GitHub / Connect GitLab,在弹窗里授权。
授权时可只勾选需要的仓库,之后可以随时调整。
从列表里选你的仓库。私有仓库只要授权过就能看到。
Cloudflare 会自动识别框架并预填,但你要逐项确认这几个关键字段:
| 字段 | 说明 | 建议值 |
|---|---|---|
| Project name | 决定 .pages.dev 域名 | 同域名,不要用下划线 |
| Production branch | 哪个分支的提交算"正式发布" | main |
| Framework preset | 预构建命令和输出目录 | 按实际框架选 |
| Build command | 安装依赖后执行的命令 | 纯静态站留空 |
| Build output directory | 构建产物的目录 | 静态站填 / 或 . |
| Root directory | 仓库里子项目的路径 | monorepo 才需要填,如 apps/web |
| Environment variables | 构建时注入的环境变量 | 区分 Production / Preview 两套 |
Cloudflare 会 clone 仓库、安装依赖、跑构建、上传产物。1–3 分钟完成,期间可以看实时构建日志。日志报错先别慌,对照下面的排查表。
几个值得知道的机制
预览部署(Preview)
任何非生产分支的 push,都会得到一个独立的预览网址,格式是 https://<commit>.项目名.pages.dev,或 https://<分支名>.项目名.pages.dev。PR 可以自动在评论里贴出预览链接。
用法:做完一个新功能,先推到 feature/xxx 分支看看效果,确认没问题再合并到 main。不用担心把生产环境搞坏。
自动注入的环境变量
CF_PAGES=1 # 在 Pages 环境里恒为 1
CI=true # CI 环境标志
CF_PAGES_BRANCH=main # 当前分支名
CF_PAGES_COMMIT_SHA=a1b2c3d # 提交哈希
CF_PAGES_URL=https://xxx.pages.dev # 生产环境地址
判断环境的小技巧:代码里写 if (process.env.CI === "true") { /* 预览环境 */ } 就能在预览地址上展示调试信息,不影响生产。
回滚:项目页 Deployments 里能看到每一次部署记录,点任意历史版本右边的 ⋯ 就能一键回滚(Promotion)。改坏了不用慌。
路线三:Wrangler 命令行
文件多、要接 CI、或者想本地先预览效果时用这条。5 条命令搞定。
不需要全局安装。下面统一用 npx 调用,它会临时拉取最新的 wrangler,省去版本管理麻烦。需要 Node.js 18+。
步骤
# 会自动打开浏览器,让你点授权
npx wrangler login
如果 CI 环境无法开浏览器,改用 API Token 环境变量:
export CLOUDFLARE_ACCOUNT_ID=你的账户ID
export CLOUDFLARE_API_TOKEN=你的API令牌
# 令牌在 dash.cloudflare.com/profile/api-tokens 创建
# 权限选 Account → Cloudflare Pages → Edit
npx wrangler pages project create
交互式提问:项目名、生产分支。这两个值会被缓存到 node_modules/.cache/wrangler,后续部署自动复用。
wrangler 4.x 的变化:新版本不再纯交互式提问,必须显式传项目名,否则报 Not enough non-option arguments。正确写法:
npx wrangler pages project create my-site --production-branch=main
npx wrangler pages dev ./dist
# 默认 http://localhost:8788
本地模拟边缘运行时,能提前发现 404、资源路径错误等问题。改完用 Ctrl + C 退出。
# 把 ./dist 换成你的构建产物目录
npx wrangler pages deploy ./dist
npx wrangler pages deploy ./dist --branch=staging
# 预览地址:https://staging.项目名.pages.dev
常用管理命令
# 查看所有 Pages 项目
npx wrangler pages project list
# 查看某个项目的所有部署(每次的独立 URL)
npx wrangler pages deployment list --project-name=my-site
# 实时查看访问日志
npx wrangler pages deployment tail --project-name=my-site
# 删除项目(会连同所有部署一起删,谨慎)
npx wrangler pages project delete
# 从零脚手架:选框架 + 自动部署(强烈推荐)
npm create cloudflare@latest -- --platform=pages
新项目强烈建议用 C3 脚手架:npm create cloudflare@latest -- --platform=pages 会引导你选框架(Vue / React / Astro / Next.js / Nuxt / SvelteKit / Hono 等),自动生成配置并询问是否直接部署,一步到位。
注意:不写 --platform=pages 的话,C3 默认创建的是 Workers 项目,不是 Pages。
路线四:用 AI 完成部署
这是最省事的一条:不打开控制台,不敲命令,在 AI 编程工具里说一句"帮我部署",AI 自己完成建项目、传文件、返回网址。
Cloudflare 官方提供 托管的远程 MCP Server 和 Skills 插件。连上之后,AI 编程助手就能读到你 Cloudflare 账户的信息、给出部署建议,并直接替你执行变更。支持 Claude Code、Cursor、Windsurf、OpenCode、Codex、Pi 等任何兼容 MCP / Agent Skills 的客户端。
方式 A:接入 Cloudflare API MCP Server(推荐)
这是覆盖最全的方式,一个 Server 打通 Cloudflare 全 API(2500+ 端点)。配置只要几行:
{
"mcpServers": {
"cloudflare-api": {
"url": "https://mcp.cloudflare.com/mcp"
}
}
}
把上面这段加到你所用客户端的 MCP 配置里。WorkBuddy 里就是写到 ~/.workbuddy/mcp.json。
连接后会跳转到 Cloudflare 页面让你登录并选择授权范围(OAuth)。授权完成后,MCP 就活了 —— 能读你的账户、项目、部署记录。
关于它的设计:只暴露 search() 和 execute() 两个工具,而不是 2594 个。AI 会针对 OpenAPI 结构现场写 JS 代码去调用,执行在隔离沙箱里。上下文占用约 1000 tokens,而不是 100 万 —— 这是它相比原生 MCP 的核心优势。
授权好后,直接对 AI 说:
可以直接复制给 AI 的指令:
帮我把这个网站部署到 Cloudflare Pages。
项目名用 my-project,产物目录是 ./dist。
部署完把访问地址发给我。
AI 会自己去确认构建产物、判断框架、调用 API 完成部署,最后把 https://xxx.pages.dev 给你。
方式 B:安装 Cloudflare Skills 插件
如果你的 AI 工具支持 Agent Skills 标准,装插件更省事(自带 MCP + 上下文知识 + 斜杠命令):
# Claude Code —— 插件市场
/plugin marketplace add cloudflare/skills
# 通用 —— npx skills CLI
npx skills add https://github.com/cloudflare/skills
# Cursor —— 也可以手动添加远程规则
# Settings → Rules → Add Rule → Remote Rule (GitHub)
# 手动克隆到技能目录:
# Claude Code ~/.claude/skills/
# Cursor ~/.cursor/skills/
# OpenCode ~/.config/opencode/skills/
# Codex ~/.codex/skills/
# Pi ~/.pi/agent/skills/
其他有用的官方 MCP Server
按需再接,不用全装:
| 用途 | Server 地址 |
|---|---|
| 查 Cloudflare 官方文档(最新版) | https://docs.mcp.cloudflare.com/mcp |
| 拉网页、转 Markdown、截图 | https://browser.mcp.cloudflare.com/mcp |
| 快速洞察应用关键指标 | https://dex.mcp.cloudflare.com/mcp |
| 启动沙箱开发环境 | https://containers.mcp.cloudflare.com/mcp |
权限提醒:MCP 授权后 AI 就能对你的 Cloudflare 账户执行变更(建项目、删部署、改 DNS)。用完可以随时在 Cloudflare 后台 My Profile → API Tokens / OAuth Grants 里撤销授权。建议审查 AI 的部署指令,别让它删你现有的线上项目。
方式 C:AI 一键脚手架
如果你连网站都还没写,可以直接让 AI 建项目并部署:
# 交互式:选框架 → 配好 → 询问是否部署
npm create cloudflare@latest -- --platform=pages
# 非交互式:直接指定一切
npm create cloudflare@latest -- --platform=pages ./my-site \
--framework=vue \
--deploy
绑定自定义域名
.pages.dev 已经完全够用。但如果要给客户看、要做 SEO,换成自己的域名更专业。
前提:域名最好已经托管在 Cloudflare
如果你的域名已在 Cloudflare 的 DNS 里,接入就是全自动的。如果还在别家 registrar,两种做法:
方案 A:把域名接入 Cloudflare(推荐)
- 在 Cloudflare 控制台点 Add a domain,输入你的域名(如
example.com) - 选择 Free 套餐
- Cloudflare 扫描出你原来的 DNS 记录,确认无误后点击继续
- Cloudflare 给你两个 nameserver,去原 registrar 把域名的 NS 改成这两个
- 等待 DNS 生效(通常几分钟到 48 小时)
- 生效后进 Pages 项目 → Custom domains → 添加域名,全部自动配置完成
额外好处:享受 Cloudflare 全套防护、缓存、分析,且不受下节提到的 Workers 域名限制。
方案 B:DNS 留在原服务商
- 先在 Pages 项目里添加域名(先做这步,Cloudflare 需要先验证归属)
- Cloudflare 会给你一条 CNAME 记录
- 去 DNS 服务商把
www或子域名指向你的项目名.pages.dev
# 在你的 DNS 服务商添加
www CNAME 你的项目名.pages.dev
限制:裸域名(example.com,不带任何前缀)在非 Cloudflare DNS 下需要 A 记录指向 IP,目前不支持。改用 www.example.com 或任意子域名都可以。
SSL 证书 完全自动,签发通常在 15 分钟内完成,不需要手动配置任何东西。
Pages 与 Workers 的关系(重要)
这一节值得读,因为 Cloudflare 官方在 2026 年调整了产品定位,可能影响你的长期选择。
官方文档现在的原话:"Workers supports most Pages use cases and offers a broader feature set. It is Cloudflare's primary platform for building applications. Start new projects with Workers."(Workers 支持 Pages 的绝大多数使用场景,且功能更广。Workers 是 Cloudflare 的主要应用平台,新项目请从 Workers 开始。)
Workers 官方主推
- 静态资源 + API + SSR 全一体
- Durable Objects、Queues、Cron
- 原生 Rollback、渐进式发布
- 更完整的日志与可观测性
- 框架适配器更新最快
- 自定义域名的 NS 必须由 Cloudflare 托管
- 没有直观的"拖文件夹"控制台
Pages
- 拖拽上传,控制台极简
- 静态托管心智负担最低
- 自定义域名不受 NS 限制
- 存量项目和教程仍完全可用
- Pages 未弃用,仍受支持
- Pages Functions 迁移中,官方文档更新略滞后
给你的实际建议
- 纯静态展示站 / 个人博客 / 作品集 → Pages 完全够用,别折腾。拖拽 3 分钟上线。
- 要跑边缘函数、SSR、写 API → 直接考虑 Workers,别从 Pages 起步。
- 已经在 Pages 上跑着的项目 → 不用急着迁,功能都能用。等有 Workers 独有能力(Durable Objects、Cron)再迁。
- 迁移命令很简单:
npx wrangler pages deploy→npx wrangler deploy,主要工作量在改配置(pages_build_output_dir→assets.directory)。
Next.js 用户注意:官方预设里还写着 npx next-on-pages@1,但这个方案基本已停止维护 —— 只支持 Edge Runtime,不能用 Node.js 内置模块(fs、crypto 等),ISR 也受限,社区 issue 积压很多。官方现在主推 OpenNext。三条路:① 纯静态导出(output: 'export',Pages 直接支持,最省事)② next-on-pages(旧,别碰)③ OpenNext(新,推荐)。
这是官方文档更新滞后于弃用公告的典型例子 —— 看到官方文档里过时的方案,务必再查一下最新公告。
带后端怎么办?比如用户登录
好消息:Cloudflare 上做后端,免费额度相当够用。但有几处硬限制必须提前知道。
结论先说:一个日活几千人的中小型项目,用户登录 + 数据库 + 文件存储,完全可以做到 0 元。真正会卡住你的不是钱,是下面列的那几个技术限制。
先搞清楚:Pages 只是"前台的静态托管"
要加后端,Cloudflare 给你的是一整套边缘产品线,它们免费额度独立计算:
| 产品 | 干什么 | 登录场景怎么用 |
|---|---|---|
| Pages / Workers | 跑代码(边缘运行时) | 写登录接口、校验 JWT、中间件 |
| D1 | 托管的 SQLite 数据库 | 存用户表、会话表、订单 |
| KV | 键值存储(最终一致) | 存 session、缓存、简单配置 |
| R2 | 对象存储(S3 兼容) | 存头像、附件、大文件 |
| Access | 零信任网关 | 给后台加一层保护 |
| Turnstile | 人机验证 | 防注册刷号、暴力破解 |
顺便解释一下这些奇怪的名字
Cloudflare 的产品命名都很有梗,了解一下能省掉不少困惑:
- D1 —— Cloudflare 的第一个 SQL 数据库(官方原话 "our first SQL database")。底层是 SQLite,所以你可以理解成「SQLite as a Service」:不用装数据库、不用管备份、不用选机房,在 Worker 里
env.DB.query()就能查。注:Cloudflare 官方从未正式说明过这个名字的确切含义,"D = Database,1 = 第一个" 是社区最通行的解读。 - KV —— Key-Value,最直白的命名,键值对存储。
- R2 —— 官方给了四个并列解释:Really Requestable、Repositioning Records、Ridiculously Reliable、Radically Reprogrammable。还暗含 R2-D2 和"S3 减去最烦的出站费"两个梗。
- Pages —— 网页,最朴素的一个。
D1 的时间线:2022 年 5 月发布公告 → 11 月 alpha → 2024 年 4 月正式 GA。
免费额度全表(2026 年 10 月官方数据)
| 项目 | 免费额度 | 超出后 |
|---|---|---|
| Workers 请求 所有后端 API 都算这里 |
100,000 次 / 天 UTC 00:00 重置 |
返回 Error 1027,可配置 fail open / closed |
| Workers CPU 时间 | 不单独计费, 每次调用上限 10 ms |
付费版默认 30 秒,最高 5 分钟 |
| 子请求 Worker 内部发出的请求 |
50 个 / 次调用 且不计费 |
付费版 10,000 个 |
| D1 读取 | 500 万行 / 天 | API 报错,当日不可查 |
| D1 写入 | 10 万行 / 天 | API 报错,当日不可写 |
| D1 存储 | 5 GB 账号总配额,单库仅 500 MB |
需删除数据或升级 |
| KV 读取 | 10 万次 / 天 | 后续操作返回错误 |
| KV 写入 | 1,000 次 / 天 | 后续操作返回错误 |
| KV 存储 | 1 GB | 付费版超出 $0.50/GB |
| R2 存储 | 10 GB / 月 | $0.015/GB-月 |
| R2 操作 | Class A 100 万/月 Class B 1000 万/月 |
$4.50 / $0.36 每百万次 |
| R2 出网流量 | 永久免费 | — |
| 静态资源托管 | 无流量限制, 静态请求不计费 |
— |
最需要注意的一条:KV 写入只有 1,000 次/天。这是整套体系里最紧的额度,比 D1 严格得多。
如果拿 KV 存 session —— 每次登录、每次刷新 token 都是一次写入 —— 几百个活跃用户就能打满。所以登录会话应该放 D1(10 万行/天写入,绰绰有余),KV 只适合存读多写少的缓存。
登录功能怎么落地:四种方案
方案一:自建(Workers + D1 + JWT)—— 最灵活,完全免费
自己写注册/登录接口,密码用 PBKDF2 或 Argon2 加盐哈希(注意:Workers 运行时没有 Node 的 bcrypt 原生模块,要用 Web Crypto API),签发 JWT 存进 HttpOnly Cookie。
my-app/
├── functions/ # Pages Functions(边缘)
│ ├── api/
│ │ ├── login.ts # POST /api/login
│ │ ├── register.ts # POST /api/register
│ │ └── me.ts # GET /api/me(读 cookie 验签)
│ └── _middleware.ts # 全局鉴权中间件
├── src/ # 前端源码
├── wrangler.jsonc
└── schema.sql # D1 建表脚本
成本:0 元。D1 的 10 万行/天写入意味着每天可以支撑上万次注册+登录。
方案二:第三方 Auth(Clerk / Auth0 / Supabase Auth)
不自建,直接用现成的登录服务。前端几行代码就有登录 UI、社交登录、密码重置、邮箱验证。
- 免费额度:Clerk 和 Supabase 都有慷慨的免费档(通常几千到一万 MAU)
- 优点:省时间,安全做得比自己写靠谱
- 缺点:超出额度要付费;数据在第三方;国内访问速度需要实测
方案三:Cloudflare Access —— 给后台加"大门"
如果你的"登录"只是保护一个管理后台(不对外开放注册),根本不用写代码。
在 Zero Trust 控制台配一条 Access 策略,绑你的 Google / GitHub 邮箱账号,只有白名单内的人能进。零代码、零数据库、无限用户。
后台管理、团队协作工具、内部 API —— 这类场景 Access 是最省事的方案,比自建一套用户系统靠谱得多。
方案四:小程序 / 移动端 App 的登录
如果是微信小程序(你的场景应该有),用户身份本来就来自 wx.login 拿到的 code。
正确姿势是:用 code 换 openid 存到 D1,而不是自己写密码登录。整个流程后端只做一次 code2session 转发,Cloudflare 完全免费。
注意:微信小程序的 wx.request 需要在后台配置合法域名(把你的 .pages.dev 或自定义域名加进「服务器域名」白名单),且必须用 HTTPS。
为什么是 SQLite,而不是 MySQL / PostgreSQL
这个问题能看出 Cloudflare 整个平台的架构思路。官方在 2022 年的发布公告里给过答案:
"SQLite is not only the most ubiquitous database in the world... it's also the first ever serverless database. SQLite was so ahead of its time, it dubbed itself 'serverless' before the term gained connotation with cloud services, and originally meant literally 'not involving a server'."
翻译:SQLite 才是「serverless」这个概念的原始持有者 —— 它本来就没有服务器,就是个文件。而 MySQL / PostgreSQL 的 DNA 里是「必须有一个常驻数据库服务器」。选 SQLite 不是因为它弱,而是因为它的架构假设和 Workers 的运行模型天然咬合。
① 嵌入式 vs 客户端-服务器
Serverless 需要的是「没有服务器」,而传统数据库必须常驻一个服务进程。
- SQLite 打开文件就能读,冷启动成本为零
- MySQL/PG 首次查询要先起连接池、TLS 握手
- 社区有句话:serverless 遇到 Postgres 会痛苦,因为每次冷启动都要重新连一次库
② 扩容方向不同:加库 vs 加机器
传统数据库靠纵向堆机器(读写分离、分库分表)。D1 换了个思路 —— 横向开多个小库。
- 官方原话:"designed for horizontal scale out across multiple, smaller (10 GB) databases, such as per-user, per-tenant or per-entity databases"
- 每个库 10 GB 上限,但库的数量免费无限(付费版单账号 5 万个)
- 用 PG 很难做,因为每个库都是一台机器
③ 单写者模型是特性
SQLite 在 WAL 模式下天然单写多读,D1 的架构正是如此:
- 每个 D1 库背后是一个 Durable Object,靠它的全局唯一性保证同一时刻只有一个活动副本
- 写操作全发往 primary,读操作走本地副本
- 一致性模型直接继承 SQLite 的 snapshot isolation
- PG 想全球多写得靠 Raft/Paxos 共识协议,复杂度和运维成本不是一个量级
④ 存储层是自研的
最容易被忽略的一点。Cloudflare 为此专门造了 SRS(Storage Relay Service):
- 官方原话:"Can we get the best of both worlds by using a local disk as a cache on top of object storage?"
- 本地磁盘做缓存 + R2 对象存储做持久化,SRS 让两层协同
- 这是 PG 生态里不存在的东西 —— 传统数据库没「存储层可以自己换」这个选项
- 同一套 SRS 也开放给了 Durable Objects(SQLite-in-DO),代码和数据同机运行,延迟更低
代价:D1 的硬限制
选 SQLite 有明确取舍。这些数字决定了什么样的项目适合 D1:
| 限制 | 免费版 | 付费版 | 意味着什么 |
|---|---|---|---|
| 单个数据库大小 | 500 MB | 10 GB | 硬上限,不可申请提升。单库超了只能拆成多个库 |
| 账号下数据库数量 | 10 个 | 50,000 个 | 免费版做多租户要留意 |
| 账号总存储 | 5 GB | 1 TB | 免费版实际能存的量很有限 |
| 写吞吐 | 单线程,约 280 INSERT / 秒 | 写密集型应用会撞墙,这是 SQLite 单写者的固有上限 | |
| 每次调用的查询数 | 50 条 | 1,000 条 | 批量操作要用 db.batch()(整个批次算 1 次) |
| Time Travel 备份窗口 | 7 天 | 30 天 | 免费版能回滚的窗口只有一周 |
| 单表行数 | 无限制(受库大小约束) | 行数不是瓶颈,库大小才是 | |
单库 500 MB 是免费版最容易被忽略的天花板。很多人以为「D1 免费版有 5GB」就够用了 —— 那 5GB 是账号下所有库加起来的配额,单个库最多只能 500MB。图片、附件、日志类数据不要往 D1 里塞,放 R2。
需要 PostgreSQL 怎么办:用 Hyperdrive
Cloudflare 并没有放弃 PG / MySQL,它有个独立产品专门干这事 —— Hyperdrive:
AWS RDS / Aurora · Google Cloud SQL · Azure Database
Supabase · Neon · PlanetScale
CockroachDB · TimescaleDB(PG 兼容)
任意自建的 PostgreSQL / MySQL 实例
Hyperdrive 做三件事:连接池管理、边缘查询缓存、压缩连接往返成本。你现有的 PG 代码一行不用改,只换 connectionString 就行:
import { Client } from "pg";
export default {
async fetch(request, env, ctx) {
// 只改了这一行:连接串从本地 DB 换成 Hyperdrive
const client = new Client({
connectionString: env.HYPERDRIVE.connectionString,
});
await client.connect();
const result = await client.query("SELECT * FROM pg_tables");
return Response.json(result.rows);
}
};
怎么选:决策表
| 你的情况 | 选谁 | 为什么 |
|---|---|---|
| 全栈在 Cloudflare,读多写少,简单关系数据 | D1 | 零配置,绑定即用,无冷启动 |
| 博客 / 表单 / 短链 / 小型 SaaS | D1 | 正好落在它的甜点区 |
| 多租户 SaaS,每个客户数据独立 | D1 | 一人一库,天然隔离,库数免费 |
| 已有 Postgres / MySQL,想搬到边缘 | Hyperdrive | 代码不用改,只换连接串 |
| 需要 PostGIS / pgvector / 复杂扩展 | Hyperdrive + PG | D1 没有 PG 的扩展生态 |
| 写密集(社交、交易、实时协作) | Hyperdrive + PG | D1 单写者约 280 INSERT/秒,写多了会排队 |
| 单个逻辑数据集 > 10GB 且无法拆分 | Hyperdrive + PG | D1 单库 10GB 是硬上限,不可申请 |
| 团队已精通 PG,迁移成本高于收益 | Hyperdrive | 官方原话:别为了统一而折腾 |
| 数据分析,几百 GB 级别 | 专业分析库 | 不适合放进 D1 或 PG |
官方的一句决策原则值得抄下来:"The decision is whether those responsibilities fit the workload better than operating or retaining PostgreSQL or MySQL."(选 D1 还是保留 PG,取决于哪一边的责任你更扛得住 —— 不是技术优劣问题,是运维成本问题。)
另外提醒供应商锁定:D1 虽然语法是标准 SQL,但 binding API、Wrangler 迁移命令、Durable Objects 语义都是 Cloudflare 特有的,迁走要重写。而一个 PG 数据库换个主机 dump + restore 就完事了 —— 这个价值平时感觉不到,搬家那天才会懂。
三个最容易翻车的技术限制
① 10ms CPU 上限
免费版每次调用只有 10 ms CPU 时间。这意味着密码哈希、复杂加密、JWT 签发这些活儿得挑轻量算法。
对策:用 Web Crypto 的 PBKDF2(迭代次数别调太高),别用 bcrypt / argon2 那种重型算法。
② 没有 Node 原生模块
Workers 跑的是 V8 隔离环境,不是完整 Node。fs、child_process、原生 bcrypt 都不存在。
对策:用 Web API(crypto.subtle、fetch),或选专门适配了 Workers 的库。
③ 控制台拖拽不支持 Functions
你要有 functions/ 目录,就必须用 Wrangler CLI 部署,控制台拖拽那套绕不过去。
对策:npx wrangler pages deploy . --project-name=xxx,函数目录会自动一起上传。
免费版超限会怎样:三种不同的表现
| 产品 | 超限行为 | 严重程度 |
|---|---|---|
| Workers | 返回 Error 1027。可设 fail open(放行,绕过 Worker)或 fail closed(返回错误页) |
鉴权类接口务必设 fail closed,否则额度耗尽时会意外放行 |
| D1 | API 直接报错,当天的读写全部不可用 | 升级 Workers Paid 通常几分钟内解除限制 |
| KV | 超限类型的操作返回错误(其他类型不受影响) | 每日 00:00 UTC 重置,熬过去就好 |
什么时候该升级付费版($5/月起)?
- Workers 请求量稳定超过 10 万/天
- 需要 30 秒以上的 CPU 时间(重计算、图像处理)
- 需要 Durable Objects、Cron、Queue 等 Pages 没有的能力
- 生产环境不能接受"额度耗尽 → 服务不可用"
付费版(Workers Standard)含每月 1000 万次请求、3000 万 CPU-ms,起步 $5/月。个人项目基本用不到这一步。
一个典型的免费登录架构
总账:这个架构跑在 Cloudflare 免费版上,月成本 0 元。按每天 1000 个新用户、每次登录 2 次读写估算,D1 写入额度会用掉 2%,Workers 请求额度用掉 1% 以内。
常见问题排查
按症状查,大部分问题都能在这里解决。
部署完了,访问显示 404
最常见的三个原因:
- 多套了一层目录。访问
https://xxx.pages.dev显示找不到文件,去构建日志看它打包了哪些路径。检查是不是传了父目录。 - 没有 index.html。Pages 靠
index.html作为根路径入口,没有它就 404。 - 单页应用(SPA)刷新 404。你的项目只有一个
index.html,路由靠前端 JS 处理。需要额外放一个404.html(内容可以是跳回首页的脚本),或在 Workers 上设not_found_handling: "single-page-application"。
图片、CSS、JS 加载不出来,页面一片空白
基本都是路径写成了绝对路径。检查代码里有没有:
src="/assets/app.js"—— 根路径开头的,在子路径下会 404background-image: url("C:\\Users\\你的名字\\...")—— 本地绝对路径
改成相对路径:src="./assets/app.js"。用浏览器开发者工具(F12 → Network)能看到具体哪个文件 404。
Git 部署时构建失败
点开构建日志看第一处报错。常见方向:
- Node 版本不匹配 → 在构建配置的环境变量里加
NODE_VERSION = 22 - 依赖没装全 → 构建命令填
npm install && npm run build - 构建输出目录填错 → 这是最高频的原因,对照前面的表格核对你的框架该填什么
- 锁文件冲突 → 本地删掉
package-lock.json/pnpm-lock.yaml重新提交,让云端用包管理器默认版本解析 - 环境变量缺失 → 在 Environment variables 里补上,注意要分别配置 Production 和 Preview
拖拽时文件标红,上传失败
单个文件超过 25 MiB。处理办法:
- 大图片转成 WebP / AVIF,通常能压到原来的 1/5
- 大视频别放静态站,走 R2 对象存储再引用
- 加
.assetsignore(Workers)或调整构建配置排除源文件,只传产物
注意:单个文件上传失败后无法单独替换,只能把整个项目重新传一遍。传之前先本地检查文件大小能省很多事。
项目名 / 域名能改吗
项目名:不能直接改。要换名字只能新建项目再重新部署。
域名:可以改。Custom domains 里可以增删,自定义域名加好后不需要重新构建。
另外,直接上传(Direct Upload)的项目控制台里没有生产分支配置项,想改只能调 API:
curl --request PATCH "https://api.cloudflare.com/client/v4/accounts/{account_id}/pages/projects/{project_name}" \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{"production_branch": "main"}'
拖拽部署的项目,之后还能改成 Git 自动部署吗
不能。用直接上传(Direct Upload)创建的项目无法再连接 Git 仓库,只能新建一个走 Git 集成的项目。
所以如果你确定要做长期项目,一开始就选 Git 集成,别用拖拽。反过来,如果只是试试看,拖拽完全没问题。
免费额度具体是多少
| 项目 | 免费额度 |
|---|---|
| 托管带宽 | 无硬性限制(Pages 不按流量计费) |
| 构建次数 | 每月 500 次(远超日常需求) |
| 构建时长 | 每次 20 分钟上限 |
| 站点数量 | 无限 |
| 静态请求 | Workers 静态资源请求免费 |
| Pages Functions | 每日 100,000 次请求免费 |
对绝大多数个人项目来说,这个额度等于"随便用,不会超"。
我的项目有后端接口 / 需要数据库怎么办
Pages 的强项是静态托管。动态需求有几种路径:
- Pages Functions(
functions/目录):边缘函数,跑在 Workers 运行时上,能连 KV / D1 / R2。注意控制台拖拽不支持编译这个目录,必须用 Wrangler 上传。 - 纯 Workers:如果需求是复杂路由、WebSocket、定时任务、邮件处理,直接用 Workers,别硬套 Pages。
- HonoX:想在 Workers 上保留文件式路由体验,这是官方推荐的框架。
判断很简单:纯展示 → Pages;需要算逻辑 → Workers。
AI 部署时它一直报错 / 连不上
- 确认 MCP 配置里 URL 完整(
https://mcp.cloudflare.com/mcp),少了结尾的/mcp会连不上 - 某些客户端强制走 SSE 传输,会失败 —— 切到 Streamable HTTP 或自动传输检测
- 授权要重做:退出 Cloudflare 登录态,清掉客户端的 OAuth 缓存后重新连
- 网络问题:MCP Server 在海外,如果网络不通可以先跑拖拽或 CLI 路线
- 如果连了多个 MCP Server,AI 可能调错了工具,明确告诉它"用 cloudflare-api 这个 server"
接下来做什么
现在就上线
按路线一拖拽,三分钟后你会拿到一个 .pages.dev 地址。
接上 AI
配好 MCP,以后让 AI 帮你改站点、查部署、看日志。
变成长期项目
迁移到 Git 集成,之后每次 push 自动部署,还有预览环境。