为什么要搞“动态”
写长文太累了。有些想法、随手拍的照片、路上看到的东西,不够写一篇文章,但又想留个痕迹。
很多博客都有“说说”或者“动态”功能,类似微博/朋友圈那种短内容流。 (2年前的博客,使用Python的FastApi做过一个轻量后端,但是因为服务器迁移等等原因….) 我也想要,但我不想为了这个功能去搞个后端:
- 不想买服务器
- 不想维护数据库
- 不想配域名 SSL
- 不想写 CRUD 接口
- 不想管用户登录
静态博客就该轻量。那怎么搞?
思路:前端纯静态,存储用 KV
我的博客是 Astro 构建的纯静态站,部署在 EdgeOne Pages 上。EdgeOne 有两个东西正好能用上:
- Edge Functions:边缘函数,写个 JS 就能当 API 用,不用部署独立服务
- KV 存储:键值数据库,类似 Redis,边缘节点就近读取
整个架构就三层:
浏览器 (Astro 静态页)
↓ fetch /api/moments
Edge Function (读/写 KV)
↓
KV 存储 (动态数据)
没有服务器进程,没有数据库连接池,没有 ORM。每个请求来的时候函数才执行,跑完就销毁。
数据结构
一条动态就这几个字段:
{
"id": "uuid",
"content": "今天天气不错",
"images": ["https://xxx.com/1.jpg"],
"location": "北京·回龙观",
"tags": ["日常"],
"createdAt": "2026-11-10T14:00:00Z"
}
图片不存数据库,只存 URL。图片本身传到图床(我用的 GitHub 仓库 + jsDelivr CDN),动态里只放链接。这样 KV 里存的就是纯 JSON,又小又快。
KV 的 Key 设计:时间倒序
KV 是按字典序排列的。要让最新的动态排在最前面,Key 的设计要巧一点:
const key = `moment_${String(9999999999999 - timestamp).padStart(13, '0')}_${id}`;
用 9999999999999 减去当前时间戳,越早的时间戳算出来的 Key 越大,越晚的时间戳 Key 越小。KV list 的时候自然就是最新在前,不用排序。
接口就两个
GET /api/moments — 读取动态
用 cursor 分页,每次 12 条:
const result = await kv.list({ prefix: 'moment_', limit: 12, cursor });
返回:
{
"items": [...],
"nextCursor": "moment_xxx"
}
前端拿到数据后直接 DOM 渲染,不用框架。翻到底部点“加载更多”带 cursor 再请求下一页。
POST /api/moments — 发布动态
发布不需要用户登录,只有我自己发。用 Bearer Token 鉴权:
const secret = env.MOMENTS_WRITE_TOKEN;
const supplied = request.headers.get('authorization')?.replace(/^Bearer\s+/i, '');
// 用 SHA-256 做常量时间比较,防时序攻击
Token 存在 EdgeOne 的环境变量里,不写在代码里。 我自己搞了一个iPhone的快捷指令,发布的时候用快捷指令或者 curl 带上 Token 就行。
前端怎么写的
Astro 页面就是静态 HTML,动态列表是空的,页面加载后 JS 发请求:
const response = await fetch('/api/moments');
const data = await response.json();
// 渲染到 #moments-list
渲染就是 createElement 拼 DOM,没用 Vue/React。一条动态就是一个卡片,带头像、时间、文字、图片墙、定位和标签。
图片点击有灯箱效果,支持左右切换、Esc 关闭、键盘方向键,纯手写。
评论怎么搞的
评论不存自己的后端,直接用 Twikoo(也是 EdgeOne Makers 部署的)。动态页底部引入一个评论组件,和文章页、友联页共用同一个 Comment.astro 组件。
技术栈
整个方案用到的东西:
| 层 | 技术 | 作用 |
|---|---|---|
| 前端框架 | Astro | 静态页面生成,SSG 输出 HTML |
| 样式 | 原生 CSS + CSS 变量 | 无 UI 框架,自己写 |
| 浏览器逻辑 | 原生 JS(无框架) | fetch 请求、DOM 渲染、灯箱 |
| 边缘函数 | EdgeOne Edge Functions | 处理 GET/POST 请求,读写 KV |
| 存储 | EdgeOne KV | 键值存储动态数据 |
| 评论 | Twikoo(EdgeOne Makers) | 独立评论系统,不存自己后端 |
| 图床 | GitHub 仓库 + jsDelivr | 图片托管,动态里只存 URL |
| 发布方式 | 手机快捷指令 / curl | 带 Bearer Token 发 POST |
| 部署 | EdgeOne Pages | 静态站托管 + 边缘函数 |
没有数据库(MySQL/PostgreSQL),没有后端框架(Express/Nest),没有 ORM,没有用户系统。
为什么不用数据库
说实话,动态这东西一个月也发不了几十条。上数据库(MySQL/PostgreSQL)完全是杀鸡用牛刀。KV 存储对这种高频读、低频写、数据量小的场景特别合适:
- 免费额度够用
- 边缘读取快
- 不用建表
- 不用管连接
- 不用备份
成本
- EdgeOne Pages:静态托管免费
- Edge Functions:每月有免费调用额度
- KV 存储:免费额度内
- 图片:GitHub 仓库免费
总共 0 元。
总结
静态博客不代表不能有动态功能。关键是别用传统思路——别买服务器、别装数据库、别写后台。用边缘函数 + KV 这种 Serverless 方案,几行代码就把“发布动态”这个需求解决了。
发布的方式也很随意:手机快捷指令发个 POST 请求,或者直接 curl 一下,动态就出现在博客上了。不用登录后台,不用打开编辑器,想说什么就说什么。

● 评论 0