把博客从 Astro 换成了 Hexo + Butterfly 主题。这篇记录一下现在的技术选型和几个实际的坑。

为什么是纯静态

博客的本质就是「把 Markdown 渲染成 HTML 然后分发出去」。一旦接受这个前提,动态博客(WordPress 那类,PHP + 数据库)就是明显的过度设计:

  • 要维护运行环境和数据库备份
  • 要操心安全补丁
  • 服务器挂了站点就挂了

静态站点把这些全部消掉——构建产物就是一堆 HTML 文件,扔到 CDN 上,没有后端可攻击,没有数据库可炸。

技术栈

层 选型 说明
生成 Hexo 8 中文社区成熟,主题生态大
主题 Butterfly 5.7 功能齐全,配置项多
托管 Cloudflare Pages 免费、全球 CDN、自动 HTTPS
搜索 hexo-generator-searchdb 构建时生成索引,无后端
评论 Giscus 基于 GitHub Discussions,无数据库
统计 Pages Functions + KV 自建,不依赖第三方

为什么不用不蒜子

中文博客做浏览量统计,默认答案通常是不蒜子(busuanzi)。但实测它的计数接口主机 events.busuanzi.ibruce.info 已经不可达——脚本能加载,数据拿不到。

所以改成自己写:一个 Cloudflare Pages Function 加一个 KV 命名空间。

1
2
3
4
5
6
7
8
9
// functions/api/views.ts 的核心逻辑
export const onRequestPost = async ({ request, env }) => {
const { path } = await request.json();

const current = Number(await env.VIEWS.get(path)) || 0;
await env.VIEWS.put(path, String(current + 1));

return Response.json({ path, views: current + 1 });
};

前端只要扫一遍页面上的计数占位符,汇总成一个请求即可。这样没有任何外部依赖,数据也在自己的账号里。

几个实际的坑

Cloudflare 绑定自定义域名时不会自动创建 DNS 记录。

这是最容易卡住的地方。域名状态会一直停在 pending,报 CNAME record not set,HTTPS 完全不可用。必须手动加一条指向 <项目名>.pages.dev 的 CNAME,而且代理(橙色云朵)必须打开。

另外,Hexo 的构建产物目录也叫 public/,和很多静态站点生成器的「静态资源目录」同名,切换框架时容易搞混。

部署流程

1
2
3
npm run server   # 本地预览,热更新
npm run build # 生成到 public/
npm run deploy # 推到 Cloudflare Pages

没有 CI、没有服务器、没有需要守护的进程。构建产物推上去,全球节点几分钟内就是最新的。