快捷菜单
常用功能一站直达
更多功能请点顶栏「快捷菜单」
来源@cusor auto(咸鱼购买)记录于2026.7.15。
结论先行:可以做出「有后台、能即时发文、边缘全球加速」的博客。
推荐路径:CNB 管代码与流水线 + Astro SSR(On-Demand) 跑在 EdgeOne Pages / Edge Functions + KV 存索引与草稿元数据 + Blob/对象存储存正文与媒体 + 轻量管理后台(同站或独立 App)。
文档日期:2026-07-15
适用对象:已有 Hugo Teek / EdgeOne / CNB 经验,希望升级「写完即见」体验的个人/小团队博客。
| 能力 | 传统 Hugo SSG | 本方案目标 |
|---|---|---|
| 发文方式 | 改仓库 → CI → 全量构建 → 部署 | 后台提交 → 写入 KV/Blob → 秒级可见 |
| 后台 | 可选(Git 编辑 / 无头 CMS) | 独立 Web 后台:登录、写稿、上传图、预览、发布 |
| 实时性 | 受 CI 时长限制(分钟级) | 发布后边缘读取最新数据(秒级);可选 SSE/WebSocket 推送「前台刷新」 |
| CDN / 边缘 | EdgeOne 托管静态 | EdgeOne Pages + Edge Function SSR + KV/Blob |
| 源码托管 | CNB / GitHub | 继续用 CNB(主题、后台、流水线都放仓库) |
「实时」在博客场景通常有两档,请先定档:
本方案两档都支持;第一档即可覆盖 95% 博客需求。
1┌──────────────┐ Git Push / PR ┌─────────────────┐
2│ 作者 / 编辑 │ ─────────────────────► │ CNB 仓库 │
3│ (浏览器后台) │ │ Astro 主题+后台 │
4└──────┬───────┘ │ CI/CD Workflow │
5 │ HTTPS API └────────┬────────┘
6 │ POST /api/posts │ build & deploy
7 ▼ ▼
8┌──────────────────────────────────────────────────────────────┐
9│ EdgeOne 边缘层 │
10│ ┌─────────────┐ ┌──────────────┐ ┌────────────────────┐ │
11│ │ Pages 站点 │ │ Edge Function│ │ Edge KV │ │
12│ │ Astro SSR │◄─┤ 鉴权/CRUD API│◄─┤ 文章索引、配置、 │ │
13│ │ HTML 流式输出│ │ 缓存失效钩子 │ │ Session、草稿态 │ │
14│ └──────▲───────┘ └──────┬───────┘ └────────────────────┘ │
15│ │ │ │
16│ │ ▼ │
17│ │ ┌──────────────┐ │
18│ └──────────┤ Edge Blob / │ 正文 Markdown、封面、 │
19│ │ COS / R2 类 │ 附件二进制 │
20│ └──────────────┘ │
21└──────────────────────────────────────────────────────────────┘
22 │
23 ▼ 访客浏览器(博客前台 + 可选「有新文章」提示)| 组件 | 职责 |
|---|---|
| CNB 仓库 | 存主题、后台前端、Edge Function 源码、CI;不存每篇文章正文(或只存初始种子内容) |
| Astro SSR | 按请求从 KV/Blob 拉数据,渲染列表/文章/标签页;可混合部分静态壳 |
| EO Edge Function | 后台 API:登录、发布、上传、删改;发布后写 KV 并清理缓存 |
| EO Pages KV | 轻量结构化数据:文章元数据索引、slug→blobKey、站点配置、登录 Session |
| EO Blob / 对象存储 | 大内容:Markdown/HTML、图片、附件;比 KV 更适合正文体积 |
| 管理后台 | Astro 同域 /admin 或独立 SPA;调用 Edge Function API |
适合:
posts:index → [{slug, title, date, tags, blobKey}])post:meta:{slug})不适合:
.md / 渲染后的 HTML 快照posts/{slug}/v{version}.md,支持回滚若当前账号 Blob 尚未开通,可用:
img.xxdevops.cn 图床只存媒体,正文仍 KV 分片(不推荐长期)Cache-Tag / purge 相关路径这正好解决你现在 Hugo 方案的痛点:发一篇文等整站构建。
1site:config → JSON 站点标题、菜单、ICP、友链开关
2posts:index → 已发布文章摘要数组(按 date 倒序,可分页切片)
3posts:drafts → 草稿 slug 列表
4post:meta:{slug} → { title, date, updated, tags, cover, status, blobKey, etag }
5auth:user:{id} → { username, passwordHash, role }
6session:{token} → { userId, exp } // 或改用签 JWT 少存 KV1content/posts/{slug}/latest.md
2content/posts/{slug}/v{n}.md
3media/{yyyy}/{mm}/{uuid}.{ext}Blob.put(draft) + KV post:meta status=draftBlob.put(latest.md)post:meta → status=publishedposts:index(插入/更新摘要)/posts/{slug}、/、/tags/*channel:updates 或向 SSE 连接广播 {"type":"post.published","slug":"..."}KV 无真正跨键事务时,应用层用 etag / 版本号 做乐观锁,失败则重试索引更新。
| 步骤 | 实现 |
|---|---|
| 读路径 | Astro getStaticPaths 不要全静态;文章页用 export const prerender = false 或 Hybrid 仅白名单静态 |
| 缓存 | Edge Function / Pages 对 HTML 设 Cache-Control: public, s-maxage=60, stale-while-revalidate=300 |
| 失效 | 发布 API 调用 EdgeOne URL 刷新 / Cache Tag 刷新 |
| 兜底 | 列表页带 ?v={indexVersion} 或 Response 头 ETag,保证 CDN 不长期脏读 |
访客行为:点发布 → 等 1 秒 → 打开首页即见新文。
/api/updates?since=ISOsite:lastPublishedAt建议上线顺序:先 A,再 A+轮询提示条「有新文章,点击刷新」。
| 方案 | 优点 | 缺点 | 建议 |
|---|---|---|---|
同域 /admin(Astro + React 岛屿) | 同源 Cookie、部署一体 | 包体进主站 | 个人博客首选 |
独立 admin.xxx.com SPA | 权限边界清晰 | 多一套 CORS/鉴权 | 多编辑协作时用 |
| 接外部 CMS(Payload / Directus / Notion) | 后台开箱即用 | 数据不在 EO KV,链路绕 | 快速原型可试 |
publishAt)/admin* 与 /api/admin/* 双层拦截auth:fail:{ip})防爆破1/ → SSR,读 posts:index 前 N 篇
2/posts/[slug] → SSR,读 meta + Blob Markdown → 渲染
3/tags/[tag] → SSR 或 ISR 短缓存
4/about → 可 prerender 静态
5/admin/* → SPA / 岛屿,强制 no-store
6/api/admin/* → Edge Function
7/api/updates → 公开,只返回 lastPublishedAt / 差量摘要Markdown 渲染:
unified + remark-gfm + rehype-pretty-code(或复用现有 shiki 配置)与现有 Hugo Teek 的关系:
1blog-astro/
2├── apps/
3│ ├── web/ # Astro 前台 + /admin
4│ └── edge-api/ # Edge Function 源码(若 EO 要求独立目录)
5├── packages/
6│ └── shared/ # 类型、Zod schema、KV key 常量
7├── scripts/
8│ ├── migrate-hugo-content.mjs
9│ └── seed-kv.mjs
10├── .cnb/
11│ └── workflows/
12│ └── deploy.yml # 推送 main → 构建 → 部署 EO Pages
13└── README.mdEO_API_TOKEN、KV_NAMESPACE、BLOB_BUCKET、JWT_SECRET 放 CNB 密钥变量,禁止进仓库v{n},后台「恢复此版本」写回 latest + 更新索引按你账号实际开通情况勾选:
若 Pages 暂时只能静态:退而求其次仍可做:
静态壳 HTML + Edge Function 注入 JSON(ESI 思路)+ 客户端 hydrate
或:
Function 直接
return new Response(html)做「穷人版 SSR」。
这两种也能「有后台、实时发布」,只是 DX 不如完整 Astro SSR。
| 维度 | 继续加深 Hugo(现有 hugo-teek-private) | Astro SSR + EO KV/Blob |
|---|---|---|
| 发文时效 | 依赖构建,难做真·秒级 | 原生适合 |
| 后台 | 你已有 oneblog-admin 方向 | 可新做或改造对接 KV |
| 主题成熟度 | Teek 生态已很完整 | 需重做/移植 UI |
| 运维 | 熟悉 | 需摸清 EO SSR 边界 |
| 实时协作写稿 | 弱 | 强(草稿云端) |
务实建议:
GET /api/time、PUT/GET KV demoPOST /api/admin/postscontent/ 写迁移脚本灌入 Blob/admin 编辑器、上传图、草稿箱posts:index + 全量 meta → COS;Blob 本身开版本/跨区域复制rehype-sanitize)| 项 | 说明 |
|---|---|
| CNB | 私有仓 + CI 分钟数,按套餐 |
| EdgeOne Pages + 流量 | 个人博客通常很低 |
| KV 读写 | 按请求计;读多要注意缓存,避免每页打爆 KV |
| Blob/COS 存储 | Markdown 可忽略;图片按现有图床策略 |
| 开发时间 | MVP 约 4~8 人周(熟悉 EO 可更快) |
优化点:HTML 边缘缓存 30~120 秒,把 KV 读从「每请求」降成「每分钟每 URL」。
| 层 | 选型 |
|---|---|
| 框架 | Astro 5 + TypeScript |
| UI | 自研 Teek 风 / shadcn 岛屿组件 |
| 编辑器 | Bytemd 或 TipTap |
| 校验 | Zod |
| 鉴权 | JWT + HttpOnly Cookie |
| 边缘 | EdgeOne Pages + Edge Functions + KV +(Blob 或 COS) |
| 仓库 / CI | CNB |
| 监控 | EO 日志 + 自建 /api/health |
| 评论 | 继续 Twikoo(与内容解耦) |
| 风险 | 对策 |
|---|---|
| EO 对 Astro SSR Adapter 支持不完整 | 阶段 0 验证;不行则 Function 直出 HTML |
| KV 无事务导致索引不一致 | 版本号 + 定期 reconcile 任务扫描 Blob |
| 误把正文只放 KV 超限 | 强制 Blob 存正文 |
| 缓存未失效导致「发布了看不见」 | 发布 API 必须 await purge;后台显示「CDN 已刷新」状态 |
| 主题迁移工作量大 | 并行域名灰度;或折中「远程内容 + Hugo」过渡 |
可以做成实时更新且带后台的博客,而且 Astro SSR + EO KV/Blob + Edge Function + CNB 是一条和技术趋势吻合、又和你现有腾讯云/EdgeOne/CNB 资产同生态的路径。
/admin + 发布即时失效缓存。astro-eo-blog,推送 Astro Skeleton + 一个读写 KV 的 Function Demo。 1// Edge Function: POST /api/admin/posts/:slug/publish
2export async function onRequest(ctx) {
3 const user = await requireAdmin(ctx); // JWT
4 const { slug } = ctx.params;
5 const body = await ctx.request.json(); // { markdown, title, tags, cover }
6
7 const blobKey = `content/posts/${slug}/latest.md`;
8 await blob.put(blobKey, body.markdown, { httpMetadata: { contentType: 'text/markdown' } });
9
10 const meta = {
11 title: body.title,
12 tags: body.tags,
13 cover: body.cover,
14 status: 'published',
15 updated: new Date().toISOString(),
16 blobKey,
17 version: Date.now(),
18 };
19 await kv.put(`post:meta:${slug}`, JSON.stringify(meta));
20
21 const index = JSON.parse((await kv.get('posts:index')) || '[]');
22 const next = upsertIndex(index, { slug, title: meta.title, date: meta.updated, tags: meta.tags });
23 await kv.put('posts:index', JSON.stringify(next));
24 await kv.put('site:lastPublishedAt', meta.updated);
25
26 await eo.purge([`/`, `/posts/${slug}`]); // 伪 API
27
28 return Response.json({ ok: true, slug, updated: meta.updated });
29} 1---
2export const prerender = false;
3const slug = Astro.params.slug;
4const meta = await kv.get(`post:meta:${slug}`, 'json');
5if (!meta || meta.status !== 'published') return Astro.redirect('/404');
6const md = await blob.get(meta.blobKey).text();
7const html = await renderMarkdown(md);
8Astro.response.headers.set('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=300');
9---
10<article set:html={html} />| 文中称呼 | 含义 |
|---|---|
| EO | 腾讯云 EdgeOne |
| KV | Edge 键值存储 |
| Blob | 边缘/对象二进制存储 |
| CNB | cnb.cool 代码托管与流水线 |
| SSR | 服务端渲染 |
| ISR / SWR | 增量再生 / 过期后后台再验证 |
本文为架构与落地建议,实施时请以 EdgeOne / Astro / CNB 当前官方文档为准,阶段 0 务必先做技术探针。
日历 · 精选 · 友链 · 更多
如果内容对你有帮助,欢迎请我喝杯咖啡 ☕



One的公众号
爱折腾博客的小白