从零搭建个人博客:Next.js + Cloudflare Pages 全流程教程

- Published on
- /8 mins read/––– views
前言
一直想搭一个自己的博客,折腾了一番之后终于上线了。这篇文章记录整个过程,从选型到部署,包括中间踩过的坑,希望能帮到有同样想法的人。
技术选型
最终选择的方案:
| 组件 | 选择 | 理由 |
|---|---|---|
| 框架 | Next.js 15 | React 生态,SSG 静态导出,性能好 |
| 样式 | Tailwind CSS | 原子化 CSS,开发效率高 |
| 内容 | MDX + Contentlayer | Markdown 写作,支持 React 组件 |
| 部署 | Cloudflare Pages | 免费额度大,全球 CDN,速度快 |
| 域名 | Cloudflare DNS | 和 Pages 无缝集成 |
为什么不用 Vercel?Cloudflare Pages 免费额度更大(无限带宽、每月 500 次构建),而且域名本身就托管在 Cloudflare,配置更方便。
第一步:Fork 开源项目
博客基于 mengke.me 二次开发。这是一个功能很完善的 Next.js 博客模板,自带:
- MDX 文章系统(代码高亮、数学公式、GFM)
- 暗色模式
- 全文搜索(Ctrl+K)
- RSS 订阅
- SEO 优化
- 标签分类 + 分页
直接 Fork 到自己的 GitHub 账号,然后 clone 到本地:
git clone https://github.com/你的用户名/你的仓库名.git
cd 你的仓库名
pnpm install第二步:个性化配置
需要修改的核心文件:
个人信息
编辑 data/author-info.ts:
export const AUTHOR_INFO = {
name: '你的名字',
description: '一句话介绍',
email: 'your@email.com',
identity: 'Student | Developer',
address: {
city: 'Your City, Country',
flag: 'flag-china', // Twemoji 国旗
timeZone: 8,
},
work: {
company: '',
occupation: 'Student',
location: 'Your City',
website: '/',
},
social: {
github: 'https://github.com/你的用户名',
// 其他社交链接按需填写
},
}网站元数据
编辑 data/site-metadata.ts:
export const SITE_METADATA = {
title: '你的博客标题',
author: '你的名字',
siteUrl: 'https://你的域名',
siteRepo: 'https://github.com/你的用户名/你的仓库',
// ...
}替换图片
public/static/images/logo.webp— 左上角 logopublic/static/images/profile.webp— 个人卡片头像
推荐用 webp 格式,体积小加载快。可以用在线工具转换,或者用 sharp-cli:
npx sharp-cli -i 你的图片.jpg -o public/static/images/profile.webp --format webp关于我页面
编辑 data/authors/default.mdx,用 Markdown 写你的自我介绍。
第三步:适配静态导出
原项目可能是为 Vercel 设计的,部署到 Cloudflare Pages 需要改成静态导出模式。
修改 next.config.js
确保有这一行:
const output = 'export'处理动态路由
output: 'export' 模式下,所有动态路由必须有 generateStaticParams()。如果某个动态路由(比如 app/snippets/[...slug]/)没有任何内容,Next.js 15 会报错:
Page "/snippets/[...slug]" is missing "generateStaticParams()"
so it cannot be used with "output: export" config.
解决方案:暂时删除没有内容的动态路由目录,等有内容了再加回来。
处理 fetch 缓存
如果代码中有 revalidate: 60 这样的增量静态再生成配置,需要改成 cache: 'no-store' 或直接删除,因为静态导出不支持 ISR。
第四步:本地测试
pnpm dev # 开发模式预览
pnpm build # 构建测试,确保没有报错构建成功后会在 out/ 目录生成所有静态文件。
第五步:部署到 Cloudflare Pages
创建 Pages 项目
- 登录 Cloudflare Dashboard
- 左侧菜单 → Workers 和 Pages
- 点击 创建 → 选择 Pages 标签页(注意不要选 Workers)
- 点击 连接到 Git → 选择你的 GitHub 仓库
填写构建配置
| 配置项 | 值 |
|---|---|
| 生产分支 | main |
| 框架预设 | Next.js (Static HTML Export) |
| 构建命令 | pnpm build |
| 构建输出目录 | out |
| 部署命令 | true |
踩坑提醒:部署命令必须填
true,不能留空(留空会报 Invalid request body),也不能填npx wrangler deploy(那是 Workers 项目用的)。
添加环境变量
展开"环境变量",添加:
| 变量名 | 值 |
|---|---|
NODE_VERSION | 20 |
保存并部署
点击"保存并部署",等待 2-3 分钟。构建成功后 Cloudflare 会分配一个 xxx.pages.dev 的临时域名。
第六步:绑定自定义域名
- 进入 Pages 项目 → 自定义域
- 添加你的域名(如
blog.example.com) - 如果域名已经在 Cloudflare DNS 托管,会自动添加 CNAME 记录
- 等待几分钟 DNS 生效
踩坑记录
坑 1:pnpm-lock.yaml 不同步
现象:构建时报 ERR_PNPM_OUTDATED_LOCKFILE
原因:修改了 package.json 的依赖但没有重新生成 lockfile。Cloudflare Pages 默认用 --frozen-lockfile 安装。
解决:
pnpm install
git add pnpm-lock.yaml
git commit -m "fix: sync pnpm-lock.yaml"
git push坑 2:创建成了 Workers 项目
现象:部署成功但访问只显示 "Hello World"
原因:在 Cloudflare 创建项目时选成了 Workers 而不是 Pages。Workers 项目没有"构建输出目录"的概念。
解决:删除 Workers 项目,重新用 Pages 方式创建。区分方法:Pages 项目设置里有"构建输出目录"字段,Workers 项目有"兼容日期"、"Workers 日志"等字段。
坑 3:空的 catch-all 路由报错
现象:Page "/snippets/[...slug]" is missing "generateStaticParams()"
原因:即使写了 generateStaticParams(),如果返回空数组,Next.js 15 在 output: 'export' 下对 catch-all 路由 [...slug] 也会报错。
解决:暂时删除没有内容的动态路由目录。
坑 4:部署命令填错
现象:Missing entry-point to Worker script or to assets directory
原因:部署命令填了 npx wrangler deploy,这是 Workers 的部署命令,Pages 不需要。
解决:部署命令改成 true。
后续可选功能
博客上线后,还可以按需配置这些功能:
- Giscus 评论 — 基于 GitHub Discussions,免费无广告
- Umami 分析 — 隐私友好的网站统计
- 浏览量统计 — 用 Cloudflare Workers + KV 实现
- Spotify 正在播放 — 用 CF Worker 代理 Spotify API
这些都是可选的,不配置也不影响博客正常运行。
自动部署
配置好之后,每次往 main 分支推送代码,Cloudflare Pages 都会自动构建和部署。写新文章只需要:
- 在
data/blog/目录下新建.mdx文件 - 写好 frontmatter 和正文
git push到 GitHub- 等 1-2 分钟自动上线
甚至可以直接在 GitHub 网页上创建文件,不需要本地环境。
总结
整个过程下来,最花时间的其实是踩坑。技术选型和配置本身不复杂,但 Cloudflare Pages 的一些细节(比如部署命令不能留空、Pages 和 Workers 的区别)文档里不太明显,需要自己摸索。
希望这篇教程能帮你少走一些弯路。如果有问题,欢迎在评论区交流。