为什么选这套方案
- Hugo:由 Go 编写,构建速度极快。Hexo 依赖 Node.js,Jekyll 依赖 Ruby,版本一换就瘫痪;Hugo 是单一二进制文件,没有这个问题。
- GitHub:内容以 Markdown 存储,天然版本控制。
- Cloudflare Pages:免费,全球 CDN,自动监听 GitHub 推送并构建,国内可访问。
整个方案运营成本接近于零。
用 npm 管理 Hugo 版本
Hugo 是独立二进制文件,通常需要手动安装。为了可移植性,使用 hugo-bin 这个 npm 包代替:
npm install hugo-bin --save-dev
npm install 时会自动下载当前系统对应的 Hugo Extended 二进制文件到 node_modules,Hugo 版本锁定在 package.json,换电脑也不需要重新配置环境:
{
"scripts": {
"dev": "hugo server",
"build": "hugo --gc --minify",
"new": "hugo new"
},
"hugo-bin": {
"buildTags": "extended",
"version": "0.147.0"
}
}
日常命令:
| 命令 | 作用 |
|---|---|
npm run dev | 启动本地预览(http://localhost:1313,热重载) |
npm run new -- posts/title.md | 新建文章,自动套用模板 |
npm run build | 构建生产环境静态文件到 public/ |
主题:PaperMod via Git Submodule
去官网 https://themes.gohugo.io/ 找自己喜欢的主题。
PaperMod 以 Git Submodule 方式引入,不直接复制主题文件。好处是主题有独立版本历史,升级时只需更新 submodule:
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
克隆仓库时需加 --recursive 参数一并拉取主题:
git clone --recursive <仓库地址>
关键配置:hugo.toml
baseURL
baseURL = 'https://your-domain.pages.dev/'
决定所有内部链接的前缀。留着默认的 example.org 不改,是最常见的坑——站点能访问,但导航栏所有链接都跳到错误域名。
搜索:必须开启 JSON 输出
PaperMod 的站内搜索是纯前端实现,依赖构建时生成的 index.json:
[outputs]
home = ["HTML", "RSS", "JSON"]
少了 "JSON",搜索框出现但无结果。
首页:ProfileMode
[params.profileMode]
enabled = true
title = "Hi, I'm xxx 👋"
subtitle = "Writing about tech, tools, and the occasional life update."
enabled = false 则首页直接变为文章列表。
导航菜单
菜单顺序由 weight 控制,数值越小越靠前:
[[menu.main]]
identifier = "posts"
name = "Posts"
url = "/posts/"
weight = 10
[[menu.main]]
identifier = "categories"
name = "Categories"
url = "/categories/"
weight = 20
[[menu.main]]
identifier = "tags"
name = "Tags"
url = "/tags/"
weight = 30
[[menu.main]]
identifier = "search"
name = "Search"
url = "/search/"
weight = 40
部署:Cloudflare Pages
- 登录 Cloudflare 控制台 → Workers & Pages → Create application → Pages → Connect to Git
- 选择博客仓库,Build settings 配置:
- Build command:
hugo --gc --minify - Build output directory:
public
- Build command:
- Environment variables 中添加:
HUGO_VERSION = 0.147.0 - Save and Deploy
必须设置
HUGO_VERSION,否则 Cloudflare 使用极旧的默认版本,PaperMod 样式会编译失败。
部署完成后获得免费的 *.pages.dev 域名,也可在后台 Custom domains 绑定自己的域名。
主题定制:侧边 TOC
PaperMod 默认 TOC 是文章顶部的可折叠块。通过 Hugo 布局覆盖机制,不修改主题文件,将 TOC 改为页面侧面的固定侧边栏。
新增两个文件:
layouts/single.html:复制自主题,将 TOC 移出<article>,放到独立<aside>,使用 Hugo 原生.TableOfContentsassets/css/extended/toc-sidebar.css:用position: fixed定位在正文侧面空白处
.toc-sidebar {
position: fixed;
top: calc(60px + 2.5rem);
left: calc(50% + 360px + 40px); /* 正文右边缘 + 间距 */
width: 200px;
}
视口宽度 ≥ 1200px 时显示,更窄时自动隐藏。主题升级时对比 themes/PaperMod/layouts/single.html 与自定义版本差异并手动同步。
渲染 Mermaid 图表
PaperMod 和 Hugo 都没有内置 Mermaid 支持,通过自定义短代码实现,两步完成:
1. 新建短代码 layouts/shortcodes/mermaid.html:
<pre class="mermaid">{{ .Inner }}</pre>
2. 在文章页引入 Mermaid CDN,在 layouts/single.html 末尾加入:
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
<script>
mermaid.initialize({ startOnLoad: true, theme: "default" });
</script>
用 {{}} 分别包裹< mermaid > 和 < /mermaid > 即可渲染,此处没有包裹是因为会强制渲染
< mermaid >
graph LR
A[开始] --> B{判断}
B -->|是| C[结束]
B -->|否| A
< /mermaid >
graph LR
A[开始] --> B{判断}
B -->|是| C[结束]
B -->|否| A
文件目录结构
blog/
├── content/
│ ├── posts/ # 博客文章(Markdown)
│ │ └── 2026/ # 文章多时按年份建子目录(URL 自动含路径)
│ └── about.md # 独立页面(如"关于")
├── static/
│ └── images/ # 图片等静态资源
│ # Markdown 中用绝对路径引用:/images/xxx.png
├── archetypes/
│ └── default.md # 新文章默认模板(含完整 Front Matter 字段)
├── assets/
│ └── css/extended/ # 自定义 CSS(自动加载,覆盖主题样式)
│ └── toc-sidebar.css
├── layouts/
│ ├── single.html # 覆盖主题文章页模板(不修改主题文件本身)
│ └── shortcodes/
│ └── mermaid.html # Mermaid 图表短代码
├── themes/
│ └── PaperMod/ # 主题(Git Submodule,不直接修改)
└── hugo.toml # 全局配置
分类 (Categories) 与标签 (Tags)
两者都是文章的筛选维度,区别在粒度:
| Categories | Tags | |
|---|---|---|
| 定位 | 文章所属领域(大方向) | 文章涉及的具体知识点 |
| 粒度 | 粗,数量少且稳定 | 细,随内容自由增长 |
| 建议数量/篇 | 1~2 个 | 3~5 个 |
在 Front Matter 中定义:
categories = ["后端开发"]
tags = ["Docker", "微服务", "部署"]
Hugo 会自动生成 /categories/ 和 /tags/ 聚合页,无需手动创建。
写作工作流
flowchart LR
A[新建文章] --> B[本地预览]
B --> C[写作]
C --> D[发布]
D --> E[推送]
E --> F[Cloudflare 自动部署]
npm run new -- posts/your-title.mdnpm run dev,打开http://localhost:1313实时预览- 写完后将
draft = true改为draft = false git add . && git commit -m "post: 文章标题" && git push- Cloudflare 自动构建,约 1 分钟后线上更新
跨设备 Clone 后初始化
博客仓库在另一台设备上 clone 后,需要两步初始化:
# 1. 安装 Hugo(hugo-bin)
npm install
# 2. 拉取 PaperMod 主题(Git Submodule)
git submodule update --init --recursive
如果 clone 时用了
git clone --recursive,第 2 步可跳过。但npm install仍然必须执行。