AI 指令:GitHub + Cloudflare Pages + Rust WASM + HTMX 零服务器全栈规范
本页面向 AI 提供构建「零独立服务器、零运维开销、毫秒级响应」的现代全栈 Web 应用规范。AI 遵循本规范时,前端基于 HTMX + Bootstrap 5 直接接收 HTML 片段,后端逻辑由 Cloudflare 边缘 Rust WASM 处理,持久化首选 Cloudflare D1 (SQLite),代码托管在 GitHub 并由 Actions 自动极速编译部署。
第一步:架构哲学与职责边界
本架构彻底摒弃传统的「自购 VPS + 挂常驻后台进程 + 编写冗余 JSON API」的沉重模式,建立基于全球边缘的轻量循环:
GitHub
作为唯一代码仓库与 CI 调度源。公开仓库下不存任何密码,通过 Actions 自动化构建编译产物。
Cloudflare 边缘
承载 Pages 静态分发与 Rust 编译的 WASM 边缘无状态函数(Functions),按需毫秒级冷启运行。
HTMX 浏览器端
遵循 HTML-over-the-Wire 模式,后端 Rust 直接吐出待替换的 HTML 结构,严禁在前端用 JS 解析 JSON 拼接 DOM。
Content-Type: text/html),由 HTMX 的 hx-swap 就地挂载。
免费额度与物理红线认知
- 单次请求 CPU 时间限制:10ms。仅计算 Rust 内部实际计算消耗,等待网络 I/O 或数据库读写不扣 CPU 时间。Rust 拼接 HTML 片段耗时通常 < 0.5ms,完全胜任。严禁在 Worker 内跑大算力挖矿、长死循环或重度图像压缩。
- 动态请求量:100,000 次 / 天。每天 UTC 0 点重置,纯静态 HTML/CSS 资源走 Pages 缓存,不计入此配额。
- 无状态(Stateless)特性与数据库演进路径:
函数随用随起、执行完即销毁。严禁使用内存全局变量(如
static mut)存储业务状态,数据必须入库。数据库阶梯演进准则(先 D1 → 后 Supabase):- 起步/轻量阶段(首选 D1 SQLite):无需自备服务器、零配置开箱即用,每日享 500 万行读 / 10 万行写的大额免费配额,极速搞定产品闭环。
- 扩展/企业阶段(平滑演进 Supabase Postgres):当数据量激增、需要复杂 SQL 分析、全文索引或要求数据完全私有化时,平滑切到自建 VPS 上的 Supabase,前端 HTMX 视图层代码 0 修改。
第二步:Rust WASM 瘦身与体积控制规范
Cloudflare 免费版限制 Worker / WASM 脚本压缩后必须小于 3 MB。Rust 默认编译会带调试符号并优先展开速度,生成文件常达数兆。AI 在初始化项目时必须按以下规约配置:
1. Cargo.toml 极限体积优化配置
[package]
name = "cf-rust-htmx-app"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
worker = "0.4" # Cloudflare 官方 Rust SDK
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
[profile.release]
opt-level = "z" # 极限精简文件大小(size-focused)
lto = true # 跨 crate 链接优化,剔除所有未使用函数
codegen-units = 1 # 单编译单元,最大化优化空间
panic = "abort" # 出错直接中止,剥离庞大的栈回溯开销
strip = true # 剔除符号表调试信息
2. HTML 渲染选型准则
- 优先使用原生
format!宏:无任何第三方模板依赖,编译产物仅几十 KB,速度与体积最优,适合简单的表单行、表格行、提示框。 - 复杂页面选用
maud宏:使用 Rust 编译期宏生成类型安全 HTML,零运行时开销,杜绝 XSS 注入风险。
第三步:持久化核心 —— Cloudflare D1 (SQLite)
ORDER BY 分页)。必须统一采用 Cloudflare D1(云原生 SQLite)!
1. D1 核心指标与优势
D1 底层是纯正的 SQLite 引擎。享有每日 500 万行读取、10 万行写入、5 GB 存储容量的免费额度。
如果表中存了 10,000 条记录,执行了一句未建索引的查询 SELECT * FROM items WHERE title = '测试',数据库必须遍历整张表,单次查询就会扣除 10,000 行读取额度!
必须遵守的防坑法则:务必为所有频繁用于 WHERE、ORDER BY、分类筛选的字段创建索引(CREATE INDEX)。命中索引后,单次查询仅消耗几行读取,500 万行读足以轻松支撑几十万用户访问!
2. 辅助利器:什么时候用 KV?(读与写的概念释疑)
答:绝对不算!读就是「读 (Get)」,写就是「保存/修改 (Put)」:
- 保存字典(写):你在发布网站时,把中文词典存入
i18n_zh,英文词典存入i18n_en。这辈子只保存了一次,总共只消耗 2 次写入额度! - 用户访问(读):今天全世界有 50,000 个用户打开你的网页,Rust 从边缘执行
kv.get("i18n_zh")取出文字渲染。这消耗了 50,000 次读取额度,而写入消耗为 0! - 黄金定论:多语言字典、全站标题电话配置,是 KV 最完美的教科书级场景(几个月存 1 次,每天几万人免费秒读)。
3. 标准建表规范 (schema.sql)
-- 初始表结构(以留言/任务为例)
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_items_created ON items(created_at DESC);
4. Rust 操作 D1 并在边缘输出 HTML
use worker::*;
// 查询最新数据并直接组装 HTML 返回
pub async fn render_item_list(env: &Env) -> Result<Response> {
let d1 = env.d1("DB")?;
let statement = d1.prepare("SELECT id, title, content, created_at FROM items ORDER BY created_at DESC LIMIT 10");
let result = statement.all().await?;
let rows: Vec<ItemRecord> = result.results()?;
let mut html = String::new();
for item in rows {
html.push_str(&format!(
r#"<li class="list-group-item bg-dark text-light border-secondary d-flex justify-content-between align-items-center">
<div>
<h6 class="mb-1">{}</h6>
<p class="mb-0 text-secondary small">{}</p>
</div>
<button class="btn btn-sm btn-outline-danger"
hx-delete="/api/items/{}"
hx-target="closest li"
hx-swap="outerHTML">
删除
</button>
</li>"#,
item.title, item.content, item.id
));
}
let mut headers = Headers::new();
headers.set("Content-Type", "text/html; charset=utf-8")?;
Ok(Response::ok(html)?.with_headers(headers))
}
第四步:GitHub Actions 自动化流水线
在仓库创建 .github/workflows/deploy.yml。开启 Rust 缓存加速,自动编译 WASM,并由 Pages Action 发布:
name: Build and Deploy to Cloudflare Pages
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Install Rust Toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- name: Rust Cache
uses: Swatinem/rust-cache@v2
- name: Install wasm-opt & worker-build
run: |
cargo install worker-build
sudo apt-get update && sudo apt-get install -y binaryen
- name: Build Rust WASM
run: |
worker-build --release
# 二次优化瘦身
wasm-opt -Oz build/worker/shim.wasm -o build/worker/shim.wasm || true
- name: Deploy to Cloudflare Pages
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: my-rust-htmx-app
directory: dist
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
第五步:极速启动前端模板(Bootstrap 5 + HTMX)
1. 极速启动极简示例模板(Bootstrap 5 + HTMX)
<!DOCTYPE html>
<html lang="zh-CN" data-bs-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rust WASM + HTMX Fullstack</title>
<link href="https://cdn.staticfile.net/bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.staticfile.net/bootstrap-icons/1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
</head>
<body class="py-5" style="background-color: #0a0e17; color: #e2e8f0;">
<main class="container" style="max-width: 760px;">
<div class="card bg-dark border-secondary p-4 mb-4 shadow">
<h2 class="h5 text-primary mb-3"><i class="bi bi-send-fill me-2"></i>发布新记录</h2>
<!-- 提交成功后清空表单,并将返回的 HTML 片段插入列表顶部 -->
<form hx-post="/api/items"
hx-target="#items-list"
hx-swap="afterbegin"
hx-on::after-request="if(event.detail.successful) this.reset()">
<div class="mb-3">
<input type="text" name="title" class="form-control bg-black text-light border-secondary" placeholder="标题" required>
</div>
<div class="mb-3">
<textarea name="content" class="form-control bg-black text-light border-secondary" rows="2" placeholder="详情内容..." required></textarea>
</div>
<button type="submit" class="btn btn-primary">提交到 Cloudflare 边缘</button>
</form>
</div>
<div class="card bg-dark border-secondary p-4 shadow">
<h3 class="h6 text-secondary mb-3">实时记录列表</h3>
<!-- 页面初始化自动触发加载 -->
<ul id="items-list" class="list-group" hx-get="/api/items" hx-trigger="load">
<div class="text-secondary small p-3 text-center">加载数据中...</div>
</ul>
</div>
</main>
<script src="https://cdn.staticfile.net/htmx/1.9.12/htmx.min.js"></script>
<script src="https://cdn.staticfile.net/bootstrap/5.3.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>
2. 如何直接套用现成 Bootstrap 5 模板(开源/商业主题)
这是 HTMX + BS5 的绝对王牌优势!传统 React/Vue 必须将现成模板重写为组件,而 HTMX 原生支持标准 HTML。你可以下载任何现成的 Bootstrap 5 后台或官网模板(如 Tabler、AdminLTE v4、SB Admin、CoreUI),通过以下四步秒变动态全栈:
- 第一步:静态资源原样放置:直接将现成模板的
css/、js/、assets/和index.html复制到你的前端静态目录。 - 第二步:圈定动态插槽容器:找到模板中需要动态更新的区域(例如表格
<tbody id="data-rows">或统计卡片<div id="stats-box">),加上专属id。 - 第三步:无侵入挂载 HTMX:在模板原本自带的翻页按钮、筛选下拉框或搜索框上,直接添加
hx-get="/api/..." hx-target="#data-rows" hx-swap="innerHTML"。 - 第四步:Rust 照抄模板 HTML 结构输出:后端 Rust 渲染时,直接复制原模板中对应的一行
<tr>或卡片<div class="...">样式类名进行字符串填充并返回。
第六步:高级演进与公开仓库安全规范
1. 平滑演进:自建 Supabase (PostgreSQL) 替代 D1
当项目业务复杂,需要真正的 PostgreSQL 全文检索、外键与独立数据自主权时,可平滑对接自建 Supabase。前端 HTMX 代码 0 修改,仅在 Rust 内部将 D1 语句换为对 Supabase PostgREST 的 HTTPS 请求:
// Rust 内部请求自建 Supabase 并直接吐 HTML 片段
pub async fn fetch_from_supabase(env: &Env) -> Result<Response> {
let base_url = env.var("SUPABASE_URL")?.to_string();
let service_key = env.secret("SUPABASE_SERVICE_ROLE_KEY")?.to_string();
let mut headers = Headers::new();
headers.set("apikey", &service_key)?;
headers.set("Authorization", &format!("Bearer {}", service_key))?;
let req = Request::new_with_init(
&format!("{}/rest/v1/items?select=*&order=created_at.desc&limit=10", base_url),
RequestInit::new().with_headers(headers),
)?;
let mut resp = Fetch::Request(req).send().await?;
let rows: Vec<ItemRecord> = resp.json().await?;
// 依然直接渲染 HTML 片段给 HTMX
let mut html = String::new();
for item in rows {
html.push_str(&format!(r#"<div class="p-2 border-bottom border-secondary">{}</div>"#, item.title));
}
let mut res_headers = Headers::new();
res_headers.set("Content-Type", "text/html; charset=utf-8")?;
Ok(Response::ok(html)?.with_headers(res_headers))
}
2. 公开仓库(Public)下的机密隔离铁律
- Cloudflare Pages 控制台:
进入
Settings→Environment variables添加机密。 勾选 Encrypt(加密机密)。机密一旦保存,即使后台也无法查看明文,仅在边缘运行时以内存方式注入,物理隔离泄露。 - GitHub 仓库控制台:
进入
Settings→Secrets and variables→Actions。 仅存放部署授权令牌CLOUDFLARE_API_TOKEN与CLOUDFLARE_ACCOUNT_ID,构建脚本无法向外界回显。 - 访客浏览器完全不可见: 访客在浏览器端抓包只能看到 Cloudflare 域名与 HTML 片段,真正的后端数据库 IP、域名及密钥完全隐匿在边缘层之后。
附录:给人类看(非 AI)—— GitHub 与 Cloudflare 免费配额速查
开发者必读本章节专供人类开发者规划项目成本与架构容量时速查。所有指标均为官方最新免费套餐(Free Tier)规约,帮助你在零服务器成本前提下充分发挥平台最大效能,安全规避物理红线:
1. GitHub 平台免费配额与规则
| 资源维度 | 公开仓库 (Public Repo) | 私有仓库 (Private Repo) |
|---|---|---|
| 仓库数量 | 无限制(自由创建) | 无限制(自由创建) |
| GitHub Actions 运行时间 | 完全无限免费 (Unlimited) | 每月免费送 2,000 分钟(Rust 增量构建带缓存约 1~2 分钟/次,月推几百次绰绰有余) |
| 代码与仓库存储空间 | 建议单仓库 ≤ 1 GB(软上限 5 GB ~ 10 GB,纯代码通常仅数 MB) | |
| 机密密钥 (Secrets) | 完全免费提供单向加密存储,公开仓库对外彻底隔离,任何人无法窥探明文 | |
Cloudflare 的免费配额是按你的整个登录邮箱账号 (Account) 统一计算并共享的,并非单个项目独占。同一账号下的所有 Worker / Pages / D1 / KV 共同消耗每日额度。如果未来不同独立项目流量极大,完全可通过注册多个不同邮箱账号实现完全物理隔离。
2. Cloudflare 平台核心组件免费配额与技术红线
| 组件类别 | 核心指标 | 免费额度 (Free Plan) | 核心技术红线与避坑说明 |
|---|---|---|---|
| Workers / Pages Functions 后端计算 |
动态请求量 | 100,000 次 / 天 (月计约 300 万次) |
每日 UTC 0 点重置。纯静态 HTML/CSS/图片走 Pages CDN 缓存,完全无限流量,不扣此额度。 |
| CPU 执行时间 | 10 ms / 单次请求 | 仅算纯 CPU 运算!等待网络或数据库 I/O 耗时不计入。Rust 拼 HTML 通常 < 0.5ms,足够使用。严禁跑大算力挖矿/复杂图像压缩。 | |
| WASM / 脚本体积 | 压缩后最大 3 MB (解压后上限 64 MB) |
必须在 Cargo.toml 开启 opt-level = "z" 与 lto = true 极致瘦身,剔除无用符号。 |
|
| 运行内存 | 128 MB | 单实例内存限制,Serverless 随用随起用完即毁,严禁依赖内存全局变量。 | |
| Cloudflare D1 SQLite 数据库 主力首选 |
读取额度 | 5,000,000 行 / 天 (500 万行) |
计算的是扫描行数!未建索引会导致全表扫描瞬间扣完。频繁查询的字段必须加 CREATE INDEX。 |
| 写入额度 | 100,000 行 / 天 (10 万行) |
完全足够满足中小企业站、博客、个人工具、论坛日常发帖。超额后当日报错,次日重置。 | |
| 存储容量 | 5 GB | 支持单库最大 10 GB。无出站流量费用(Egress 0 元)。 | |
| Workers KV 键值缓存 辅助加速 |
读取次数 | 100,000 次 / 天 | 毫秒级(0~2ms)全球边缘本地内存直出,多语言词典、全局配置首选。访客查看只算读,完全不算写! |
| 写入 / 删除 | 仅 1,000 次 / 天 | 极低额度警示!严禁用于评论、发帖或高频点赞。同一 Key 写入上限为 每秒最多 1 次。 | |
| 数据有效周期 | 原生支持 TTL 自动过期 | 支持设置秒级自动过期(如 expirationTtl: 600),到期全球自动删除,不占写/删额度。 |
|
| 存储与单值 | 1 GB 存储 单值最大 25 MB |
单 Key 下可存大文件(如前端大 HTML 或供浏览器客户端下载执行的 WASM 模块)。 | |
| Pages CI 构建 | 每月自动构建 | 500 次 / 月 | 平均每天可通过 git push 触发 16 次以上自动部署上线,单次构建超时 20 分钟。 |