从零搭建 Hugo 博客并部署到 GitHub Pages
背景
之前博客用 Next.js + Express + PostgreSQL 搭的,一套下来几十个依赖,光登录页的 redirect loop 就修了好几次。写个博客而已,搞这么重干嘛?
决定迁移到 Hugo —— 纯静态,Markdown 写文章,git push 自动部署,零运行时依赖。
1. 创建 GitHub 仓库
新建一个公开仓库 blog-hugo。
2. 初始化 Hugo 项目
本地安装 Hugo(extended 版本,支持 Sass):
# Linuxwget https://github.com/gohugoio/hugo/releases/download/v0.147.0/hugo_extended_0.147.0_linux-amd64.tar.gztar xz && sudo mv hugo /usr/local/bin/
# macOSbrew install hugo初始化站点:
hugo new site blog-hugocd blog-hugogit initgit remote add origin https://github.com/你的用户名/blog-hugo.git3. 选择主题
用了 PaperMod —— 极简风格,自带深色模式、搜索、标签、分类,社区最大。
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod配置 hugo.toml:
baseURL = 'https://你的用户名.github.io/blog-hugo/'languageCode = 'zh-CN'title = "My Blog"theme = 'PaperMod'
[params] author = '你的名字' description = 'Personal blog' defaultTheme = 'auto' ShowReadingTime = true ShowPostNavLinks = true ShowBreadCrumbs = true ShowCodeCopyButtons = true
[params.homeInfoParams] Title = "Hi there 👋" Content = "Welcome to my blog"
[[menu.main]] identifier = 'home' name = 'Home' url = '/' weight = 10[[menu.main]] identifier = 'posts' name = 'Posts' url = '/posts/' weight = 20[[menu.main]] identifier = 'categories' name = 'Categories' url = '/categories/' weight = 30
[outputs] home = ['HTML', 'RSS', 'JSON']4. 迁移旧文章
之前文章存在 PostgreSQL 里,用 Node.js 连数据库导出成 Markdown 文件。
每篇文章对应一个 .md 文件,放在 content/posts/ 目录下:
---title: "文章标题"date: 2026-05-01T00:00:00+08:00draft: falsecategories: ["分类名"]tags: ["标签1", "标签2"]description: "文章摘要"---
正文内容...5. 配置 GitHub Actions 自动部署
创建 .github/workflows/deploy.yml:
name: Deploy Hugo Blog to GitHub Pages
on: push: branches: [main] workflow_dispatch:
permissions: contents: write
jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0
- name: Setup Hugo uses: peaceiris/actions-hugo@v3 with: hugo-version: 'latest' extended: true
- name: Build run: hugo --minify --baseURL "https://你的用户名.github.io/blog-hugo/"
- name: Deploy to docs folder run: | cp -r public /tmp/public git checkout main rm -rf docs mkdir -p docs cp -r /tmp/public/* docs/ git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git add docs/ git commit -m "deploy: update site" || echo "No changes" git push6. 启用 GitHub Pages
在仓库 Settings → Pages 中,设置:
- Source: Deploy from a branch
- Branch:
main/docs文件夹
每次 push 到 main 分支,Actions 自动构建 Hugo 并把产物推到 docs/ 目录,GitHub Pages 自动部署。
7. 日常写文章
在本机 clone 仓库后:
# 写新文章hugo new content content/posts/my-new-post.md
# 编辑文章vim content/posts/my-new-post.md
# 本地预览hugo server --buildDrafts
# 发布:一条命令搞定git add . && git commit -m "new post: xxx" && git push也可以设置 git alias 更省事:
git config alias.publish '!git add . && git commit -m "update posts" && git push'之后写完文章只需要 git publish 一条命令。
遇到的坑
坑 1:TOML 字符串转义
# ❌ 错误:单引号内反斜杠转义会报错title = 'ddd\'s Blog'
# ✅ 正确:用双引号title = "ddd's Blog"坑 2:Hugo 版本不兼容
PaperMod 最新版要求 Hugo 0.146+。如果遇到 Min 0.146.0 错误,升级 Hugo 即可。
坑 3:Pages 构建模式
GitHub Pages 有 legacy 和 workflow 两种构建模式:
legacy:GitHub 自己跑 Jekyll 构建。纯静态 HTML 需要加.nojekyll文件跳过 Jekyllworkflow:由 Actions 构建。但 Pages 自己也会触发一次构建,可能冲突
最终方案:Actions 把构建产物推到 main 分支的 docs/ 目录,Pages 用 legacy 模式读 main/docs。最稳。
总结
| 项目 | 之前 | 现在 |
|---|---|---|
| 前端 | Next.js + React + Tailwind | Hugo + PaperMod |
| 后端 | Express + PostgreSQL | 无(纯静态) |
| 认证 | express-session + bcrypt | 无 |
| 部署 | Docker 容器 | GitHub Pages |
| 写文章 | 登录后台 → API 存数据库 | 本地写 .md → git push |
| 自动部署 | 无 | GitHub Actions |
整个博客现在只需要一个 git 仓库,写完文章 push 就上线,再也不用管服务器、数据库、Session 这些东西了。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!