返回首页

Next.js 个人博客 — 开发与部署指南

2026-06-10T00:00:00.000Z11 min read 分钟Next.js, Cloudflare, 教程, 前端

从零搭建一个基于 Next.js 的静态技术博客,通过 Cloudflare Pages 免费部署上线。本文涵盖技术架构、项目结构、开发流程、部署配置等完整指南。

项目概述

本项目是一个基于 Next.js 的静态个人技术博客,通过 Cloudflare Pages 免费部署上线。采用 Markdown 写文章、next build 生成纯静态 HTML、wrangler 推送到 Cloudflare 全球 CDN 的架构,实现了零服务器成本、自动 HTTPS、国内可访问的完整博客体验。

技术架构与原理

整体工作流程如下:

text
编写 Markdown 文章
        ↓
  Next.js 静态构建 (next build + output: "export")
        ↓
  生成纯 HTML/CSS/JS 到 out/ 目录
        ↓
  wrangler pages deploy → Cloudflare 全球 CDN
        ↓
  用户访问 *.pages.dev

为什么选择静态导出? Next.js 的 output: "export" 模式会在构建时把所有页面预渲染为独立的 HTML 文件,不依赖 Node.js 服务器运行。这意味着它可以部署到任何静态托管平台(Cloudflare Pages、GitHub Pages、Netlify 等),零运维成本。

为什么用 Cloudflare Pages? 相比 Vercel 的 .vercel.app 域名在国内几乎无法访问的问题,Cloudflare 在中国大陆有 CDN 节点,.pages.dev 域名通常可以直接打开,且免费套餐完全满足个人博客需求。

技术栈

层面技术说明
框架Next.js 16 + React 19App Router 架构,支持 SSG
样式Tailwind CSS 4原子化 CSS,暗色科技风主题
主题切换next-themes亮色/暗色自动切换,class 策略
文章引擎gray-matter + react-markdown解析 Markdown frontmatter + 渲染正文
代码高亮rehype-highlight基于 highlight.js 的语法高亮
Markdown 增强remark-gfm支持表格、任务列表、删除线等
图标lucide-react轻量 SVG 图标库
部署Cloudflare Pages + wrangler全球 CDN,免费
CI/CDGitHub Actions推送代码自动部署

项目结构

text
myblog/
├── content/posts/           # Markdown 博客文章(核心内容目录)
│   ├── hello-world.md
│   ├── nextjs-performance-optimization.md
│   └── react-hooks-best-practices.md
├── src/
│   ├── app/                 # Next.js App Router 页面
│   │   ├── layout.tsx       # 根布局(字体、ThemeProvider、侧边栏)
│   │   ├── page.tsx         # 首页(文章列表)
│   │   ├── HomeContent.tsx  # 首页客户端组件(标签筛选交互)
│   │   ├── globals.css      # 全局样式 + 暗色主题变量
│   │   ├── blog/[slug]/     # 文章详情页(动态路由)
│   │   │   └── page.tsx
│   │   └── resume/          # 简历页
│   │       ├── page.tsx
│   │       └── PrintButton.tsx
│   ├── components/          # 可复用 UI 组件
│   │   ├── Sidebar.tsx      # 左侧边栏(头像、简介、导航)
│   │   ├── PostCard.tsx     # 文章卡片
│   │   ├── TagFilter.tsx    # 标签筛选
│   │   ├── TableOfContents.tsx  # 文章目录
│   │   ├── ThemeToggle.tsx  # 主题切换按钮
│   │   └── ...
│   └── lib/
│       └── posts.ts         # 文章读取/解析/排序工具函数
├── public/                  # 静态资源
├── .github/workflows/       # GitHub Actions 自动部署
│   └── deploy.yml
├── next.config.ts           # Next.js 配置(静态导出)
└── package.json

本地开发

环境要求

  • Node.js >= 22
  • npm >= 10

初始化项目

bash
git clone https://github.com/YinxuanLuo/nextjs-boilerplate.git
cd nextjs-boilerplate
npm install

启动开发服务器

bash
npm run dev

浏览器访问 http://localhost:3000,支持热更新——修改代码或文章后页面自动刷新。

常用命令

bash
npm run dev      # 启动开发服务器(热更新)
npm run build    # 生产构建,静态文件输出到 out/ 目录
npm run lint     # 代码规范检查

写博客文章

创建新文章

content/posts/ 目录下新建 .md 文件,文件名即为 URL 路径(slug)。例如:

text
文件路径: content/posts/my-new-post.md
访问地址: https://myblog-3rz.pages.dev/blog/my-new-post/

文章格式

每篇文章由 frontmatter(元数据) + Markdown 正文 两部分组成:

markdown
---
title: "文章标题"
date: "2026-06-10"
summary: "一句话描述文章内容"
tags: ["React", "前端"]
draft: false
---

## 第一个标题

正文内容,支持完整的 Markdown 语法...

\`\`\`tsx
function Hello() {
  return <h1>Hello World</h1>;
}
\`\`\`

frontmatter 字段说明

字段类型必填说明
titlestring文章标题,显示在详情页和卡片上
datestring发布日期,格式 YYYY-MM-DD,用于排序
summarystring文章摘要,显示在首页卡片上
tagsstring[]标签数组,用于分类筛选
draftboolean设为 true 时文章不会出现在列表中

文章解析原理

src/lib/posts.ts 中的核心流程:

  1. fs.readdir 扫描 content/posts/ 下所有 .md 文件
  2. gray-matter 解析 frontmatter(--- 之间的 YAML 部分)和正文
  3. reading-time 根据正文字数计算阅读时长
  4. 按日期降序排列,返回文章元数据数组

文章详情页通过 react-markdown + remark-gfm + rehype-highlight 将 Markdown 渲染为带样式的 HTML,自定义渲染器为标题添加锚点、为代码块添加语言标签和语法高亮。

构建与部署

构建配置

next.config.ts 是整个部署方案的核心:

ts
const nextConfig: NextConfig = {
  output: "export",       // 静态导出模式
  trailingSlash: true,    // URL 尾部加 /,确保子目录有 index.html
  images: {
    unoptimized: true,    // 静态导出不支持 next/image 优化
  },
};

output: "export" 的原理: Next.js 在构建时会遍历所有路由,把每个页面预渲染成独立的 HTML 文件。比如 /blog/hello-world/ 会生成 out/blog/hello-world/index.html。这些文件可以直接被任何静态服务器托管,不需要 Node.js 运行时。

trailingSlash: true 的作用: 让 Next.js 把每个路由输出为 目录/index.html 而非 文件.html。Cloudflare Pages 对目录型路由的解析更友好,访问 /blog/hello-world/ 时会自动找到 blog/hello-world/index.html

手动构建与预览

bash
npm run build          # 构建,输出到 out/ 目录
npx serve out          # 本地预览静态文件

手动部署到 Cloudflare Pages

前置条件:安装 wrangler 并登录。

bash
npm install -g wrangler           # 安装 Cloudflare CLI
wrangler login                    # 浏览器授权登录
wrangler pages project create myblog --production-branch main   # 首次创建项目
wrangler pages deploy out --project-name=myblog --branch=main --commit-dirty=true  # 部署

部署原理: wrangler pages deploy 会把 out/ 目录下的所有文件上传到 Cloudflare 的边缘网络。Cloudflare 自动为 *.pages.dev 域名配置 HTTPS 证书和全球 CDN 加速。每次部署会生成唯一的部署 URL,同时 production 分支会更新主域名。

自动部署(GitHub Actions)

推送代码到 GitHub 后自动触发构建和部署,无需手动运行 wrangler。

工作流程

text
git push → GitHub Actions 触发
    ↓
checkout 代码 → 安装依赖 → npm run build
    ↓
cloudflare/wrangler-action 部署 out/ 到 Cloudflare Pages
    ↓
线上自动更新

配置文件

.github/workflows/deploy.yml

yaml
name: Deploy to Cloudflare Pages

on:
  push:
    branches: [master]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm run build
      - uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          command: pages deploy out --project-name=myblog --branch=main --commit-dirty=true

配置步骤

第一步:创建 Cloudflare API Token

  1. 打开 https://dash.cloudflare.com/profile/api-tokens
  2. 点击 Create Token → 选择 "Edit Cloudflare Workers" 模板
  3. 权限确认包含:Cloudflare Pages: WriteAccount Settings: Read
  4. 资源选择你的账号,创建并复制 Token

第二步:设置 GitHub Secret

  1. 打开仓库的 Settings → Secrets and variables → Actions
  2. 点击 New repository secret
  3. Name 填 CLOUDFLARE_API_TOKEN,Value 粘贴 Token
  4. 保存

配置完成后,每次向 master 分支推送代码,GitHub Actions 会自动构建并部署到 Cloudflare Pages。

日常开发工作流

bash
# 1. 写新文章:在 content/posts/ 下新建 .md 文件

# 2. 本地预览
npm run dev

# 3. 确认无误后提交代码
git add .
git commit -m "add: 新文章标题"
git push origin master

# 4. GitHub Actions 自动部署,几分钟后线上更新

自定义修改指南

想改什么去哪里改
个人信息(名字、职位、简介)src/components/Sidebar.tsx
技能标签src/components/Sidebar.tsxskills 数组
社交链接(GitHub、邮箱)src/components/Sidebar.tsx 底部社交区域
主题颜色src/app/globals.css 的 CSS 变量
简历内容src/app/resume/page.tsx 的数据数组
首页欢迎文案src/app/page.tsx 的 header 部分
导航菜单src/components/NavLinks.tsxnavItems

常见问题

为什么不用 Vercel 部署? Vercel 的 .vercel.app 域名在中国大陆被 DNS 污染,几乎无法访问。Cloudflare Pages 的 .pages.dev 域名在国内网络下通常可以正常打开。

静态导出有什么限制? 不支持需要服务器运行的功能:API Routes、getServerSidePropsnext/image 自动优化、中间件等。但对博客这类内容站来说,纯静态完全够用,而且加载速度更快。

如何绑定自定义域名? 在 Cloudflare Dashboard → Pages → myblog → Custom domains 中添加域名。如果域名在 Cloudflare 管理,DNS 会自动配置;否则需要手动添加 CNAME 记录指向 myblog-3rz.pages.dev

文章里的图片怎么放? 将图片放到 public/ 目录下,在 Markdown 中用 /图片名.png 引用。也可以直接使用外部图床链接。注意静态导出不支持 next/image 的自动优化。