用 Cloudflare 免费搭一个个人博客
想搭个人博客这件事拖了很久。不是没有想过,而是每次评估一圈下来都觉得麻烦:买服务器要花钱,用现成的平台又有各种限制,域名备案的事情也不想碰。后来我发现 Cloudflare 的免费套餐其实够用,加上 Astro 的静态站点方案,整件事的成本可以压到只剩一个域名费用。
选什么框架
博客的需求很简单:写 Markdown,渲染成页面,部署出去。满足这个条件的框架不少,Hugo、Jekyll、Next.js、Nuxt,都能做。
我最后选了 Astro。原因主要有两点。第一,Astro 默认就是静态优先的,生成出来的 HTML 基本上不带多余的 JavaScript,页面加载很快。第二,它支持 MDX,意味着我可以在文章里嵌组件,虽然目前还没用上,但留着不碍事。
Astro 官方有一个博客模板,直接用这个起手:
pnpm create astro@latest -- --template blog
跑完之后目录结构就出来了,博客文章放在 src/content/blog/ 里,每篇文章是一个 .md 或者 .mdx 文件,frontmatter 里写 title、description、pubDate 这几个必填字段。
部署到哪
Cloudflare 有两个产品可以部署静态站点:Pages 和 Workers。
Pages 更简单,连上 GitHub 仓库之后,每次 push 自动触发构建和部署,不需要自己配 CI。Workers 更底层,可以跑自定义的服务端逻辑,但配置稍微麻烦一点。
如果只是纯静态博客,Pages 完全够了。我最后选了 Workers,主要是因为之后想在博客里加一些动态功能,比如文章浏览计数或者评论,提前用 Workers 省得以后迁移。
两个方案的免费额度都很宽:
- Pages:每月 500 次构建,带宽不限,自定义域名免费
- Workers:每天 10 万次请求,CPU 时间 10ms/请求,对博客来说完全用不完
配置 Workers 部署
Astro 要部署到 Workers,需要装 @astrojs/cloudflare 适配器:
pnpm add @astrojs/cloudflare
然后在 astro.config.mjs 里启用它:
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare(),
site: 'https://yourdomain.com',
});
再在项目根目录建一个 wrangler.jsonc,告诉 Cloudflare Workers 怎么运行这个项目:
{
"name": "my-blog",
"compatibility_date": "2025-01-01",
"main": "./dist/_worker.js/index.js",
"assets": {
"directory": "./dist",
"binding": "ASSETS"
},
"environments": {
"production": {
"route": "yourdomain.com/*"
}
}
}
部署命令:
pnpm build && wrangler deploy --env production
第一次跑的时候会让你登录 Cloudflare 账号,浏览器里走一下授权流程就好。
域名怎么处理
如果你已经有一个域名,把它托管到 Cloudflare 就行。进 Cloudflare Dashboard,添加域名,然后去你的域名注册商那里把 DNS 服务器改成 Cloudflare 给的那两个 nameserver,等待生效,通常半小时以内。
域名托管到 Cloudflare 之后,SSL 证书是自动签发的,不需要额外配置。HTTPS 就这么有了。
如果还没有域名,注册一个 .com 大概每年 10 美元左右。这是这套方案里唯一需要花钱的地方。如果连域名钱也不想花,可以用 Cloudflare Pages 提供的 *.pages.dev 免费子域名,同样支持 HTTPS。
写作流程
配好之后,写文章就是在 src/content/blog/ 里新建一个 .md 文件,写 frontmatter,然后正文用 Markdown 写。
本地预览:
pnpm dev
写完之后推到 GitHub,如果配了 CI 就自动部署,没配的话手动跑一下 pnpm deploy 也行。
我目前用的是手动部署,还没有接 CI,每次改完本地确认没问题再推。博客更新频率不高,这样反而更简单。
踩过的坑
有一点值得提一下。Astro 配合 @astrojs/cloudflare 之后,部分 Node.js 内置模块在运行时是不可用的,因为 Workers 的 runtime 不是 Node.js,而是基于 V8 的 workerd。如果你在代码里用了 node:fs、node:path 这些模块,构建可以过,但运行时会报错。
这个问题的解法是在 wrangler.jsonc 里启用 nodejs_compat 兼容标志:
{
"compatibility_flags": ["nodejs_compat"]
}
不过更推荐的方式是尽量避免在运行时依赖 Node.js 专有 API,把需要文件系统的逻辑移到构建阶段处理。这样生成出来的 Worker 代码更干净,也不依赖兼容层。
整体感受
跑起来之后,整个方案的维护成本很低。Cloudflare 的基础设施帮你处理了 CDN、SSL、DDoS 防护这些事情,博客本身没有数据库,没有服务器需要管,出问题的概率很小。
速度也不错。静态资源走 Cloudflare 的 CDN 节点,国内访问延迟基本在 50ms 以内。
唯一的限制是 Workers 的 CPU 时间:每次请求最多 10ms(免费套餐)。对于博客这种场景完全不是瓶颈,但如果你想在上面跑一些计算密集的东西,就得注意了。