博客迁移记:从 VPS 到 Cloudflare Pages

关掉那台每个月 5 美元的 VPS 之后,我把博客搬到了 Cloudflare Pages。记录迁移过程、踩到的坑,以及一年下来的实际账单。

博客迁移记:从 VPS 到 Cloudflare Pages

那台 VPS 我续费了三年。它跑着一个 Nginx、一个 Node 进程、一个自动续期的 certbot 定时任务,以及一块我自己都忘了里面有什么的挂载盘。

终于在某次半夜收到「磁盘写满」告警之后,我决定把它关掉。

迁移前的状态

VPS:1 核 1G,每月 $5
  ├── Nginx 反代
  ├── Node SSR 进程(PM2 守着,崩过 7 次)
  ├── SQLite 存浏览量
  ├── certbot 自动续证书
  └── 我自己写的部署脚本(用 rsync + ssh)

每月维护成本:约 40 分钟

真正的问题不是钱,是那 40 分钟。每次想改点东西,都要先回忆起部署脚本怎么用的。

迁移步骤

1. 内容搬出来

原来文章存在 SQLite 里,写了个脚本导出成 Markdown:

const rows = db.prepare('SELECT * FROM posts ORDER BY published_at DESC').all();
for (const row of rows) {
	const frontmatter = [
		'---',
		`title: ${row.title}`,
		`description: ${row.summary ?? ''}`,
		`published: ${row.published_at}`,
		`category: ${row.category}`,
		`tags: [${(row.tags ?? '').split(',').filter(Boolean).join(', ')}]`,
		'---',
		'',
	].join('\n');
	await writeFile(`src/content/blog/${slug}.md`, frontmatter + row.body);
}

2. 浏览量数据别丢

导出成 JSON,写进 KV:

pnpm exec wrangler kv key put --binding=BLOG_KV \
  "post:/blog/hello-world/" '{"views":1204,"likes":37}'

3. 接上 Pages

在 Dashboard 里连上 GitHub 仓库,构建配置:

Build command:       pnpm build
Build output dir:    dist
Node version:        22
环境变量:            NODE_VERSION=22

踩到的三个坑

坑一:大小写敏感。 本地 macOS 不区分大小写,Linux 构建机区分。import Foo from './foo' 在本地能跑,线上就报错。加了个 lint 规则强制检查。

坑二:重定向没配。 老站点的 URL 是 /post/123,新站是 /blog/slug/。忘了配重定向,搜索引擎里的链接全变 404。后来用 public/_redirects 补上:

/post/:id    /blog/:id    301

坑三:构建缓存。 Pages 会缓存 node_modules,有时依赖更新了但缓存没失效。遇到过一次「代码改了,构建产物没变」,加了 pnpm install --force 才排查出来。

一年后的账单

项目用量费用
Pages 构建380 次$0
Pages 请求约 90 万次$0
Functions 请求约 12 万次$0
KV 读 / 写210 万 / 3.4 万$0
域名1 个$11 / 年
合计$11 / 年

从每月 5 美元 + 40 分钟维护,变成每年 11 美元 + 0 分钟维护。

现在的部署流程

git add .
git commit -m "post: 新文章"
git push

完事。CI 会在两分钟内完成构建、生成搜索索引、部署到全球节点。

现在唯一的运维工作是:每年续一次域名。

评论区还没开张 —— 想开启的话,把 src/data/site.ts 里FEATURES.comments 的 enabled 设为 true 并填入 giscus 配置即可。

也许你还想看