这个博客从今天起不再跑在我家的树莓派上了。前后端整体迁到了 Cloudflare Workers,域名也换成了现在你看到的这个。记录一下完整过程。
为什么迁
博客跑在树莓派 + Cloudflare Tunnel 上两个月,能用,但:家里断网就下线、树莓派要兼职跑其他服务、备份全靠自觉。博客这种纯 Web 应用,其实是最适合 Serverless 的负载。
目标架构:一个 Worker 搞定所有
freakz2z.com
└── Cloudflare Worker (Hono)
├── Static Assets → 前端构建产物(SPA)
├── /api/* → 后端路由
├── /uploads/* → R2 存储
└── D1 → SQLite 数据库
关键决策是不用 Pages + Workers 分离,而是单 Worker 挂 Static Assets。前后端同源,CORS 问题不存在,前端的 baseURL: '/api' 一行不用改。
// wrangler.jsonc
"assets": {
"directory": "../client/dist",
"not_found_handling": "single-page-application",
"run_worker_first": ["/api/*", "/uploads/*", "/sitemap.xml"]
}
runworkerfirst 是精髓:静态资源直出,只有这几类路径进 Worker 逻辑。
Express → Hono
九个路由文件全部手工移植。Hono 的 API 和 Express 神似,大部分是机械劳动:
// Express
router.get('/:id', async (req, res) => res.json(data));
// Hono
app.get('/:id', async (c) => c.json(data));
值得一提的坑:hono/jwt 的 verify 必须显式传算法 verify(token, secret, 'HS256'),不传直接抛 JwtAlgorithmRequired。所有带鉴权的接口集体 401,排查了好一会。
bcrypt → PBKDF2
Workers 免费版单请求 CPU 时间 10ms,bcrypt 一次哈希就要几十上百毫秒,直接超限。换成 WebCrypto 原生支持的 PBKDF2(10 万次迭代),登录接口瞬间恢复正常。
密码哈希格式设计成自描述的:pbkdf2$100000lt;salt>lt;hash>,以后想换参数或算法可以平滑过渡。
文件存储 → R2
multer 磁盘存储换成 R2 put(),/uploads/* 路由从 R2 读取并加 7 天缓存头。URL 结构不变,历史文章里的图片链接全部原样可用。
一个本地开发的坑:wrangler CLI 往本地 miniflare R2 上传中文文件名会被百分号编码,线上没这个问题。本地调试图片 404 时别慌,先看看 key 长什么样。
数据迁移
MySQL → D1 的方言部分之前写过一篇,这里只说流程:脚本从 MySQL 导出 JSON → 程序化生成 INSERT → wrangler d1 execute 灌入。迁完逐表 COUNT 对比,再抽了几篇文章做字节级 diff,确认内容零丢失(连访问计数都原样保留了)。
效果
- 全球边缘节点响应,不再受家庭宽带上行限制
- 树莓派卸下博客负载,安心跑别的
- 免费额度(10 万请求/天)对个人博客来说根本用不完
如果你也有个跑在自己设备上的小站,认真考虑一下这条路。