使用 GitHub Actions 自动部署 Hexo 博客
每次写完一篇博客,在本地 hexo s 预览完觉得没问题了,还得手动敲一遍 hexo g && hexo d,等它慢慢推到 GitHub 上……说实话,烦死了。有几次我写完文章都凌晨两点了,敲完部署命令就去睡了,第二天起来发现 TM 的部署失败了,原因是本地 Node 版本跟远程不一致,生成的页面样式全崩了。
后来我寻思,这玩意儿不就是 CI/CD 最典型的场景吗?push 代码 → 自动构建 → 自动部署。GitHub Actions 免费额度够用,配一次永久生效,咱就搞起来吧。
为什么要自动化部署
先说说我之前手动部署的痛苦:
- 本地环境不稳定 —— 我电脑上装了 Node 16、18、20 三个版本(用 nvm 管理的),有时候切错版本,
hexo generate直接报错 - 忘记部署 —— 有好几次文章写完了,commit 推上去了,结果忘了
hexo d,过了两天才发现博客上还是旧内容 - 换电脑就抓瞎 —— 出去玩的时候用笔记本写文章,结果那台机器没装 Hexo 环境,还得现装
用 GitHub Actions 的话,这些问题统统不存在了。只要 git push,剩下的交给 CI 搞定。
GitHub Pages 的两种部署方式
现在 GitHub Pages 支持两种部署方式,咱先对比一下:
方式一:分支部署(传统方式)
把构建产物推到 gh-pages 分支,GitHub 从这个分支部署。用 peaceiris/actions-gh-pages 这个 Action 可以轻松搞定,也是目前 Hexo 社区用得最多的方案。
优点:配置简单,社区成熟,坑少
缺点:需要维护一个 gh-pages 分支
方式二:GitHub Actions 部署(官方新方式)
2022 年 GitHub 推出的官方方案,使用 actions/upload-pages-artifact + actions/deploy-pages,直接通过 Artifact 部署,不需要 gh-pages 分支。
优点:官方方案,不需要额外分支
缺点:需要配置 OIDC 权限(id-token: write),稍微复杂一点
两种方式都能用,选哪个看个人喜好。我个人推荐方式一,因为 peaceiris/actions-gh-pages 配置更简洁,踩坑也少。
完整 Workflow 配置
方式一:使用 peaceiris/actions-gh-pages(推荐)
在你的 Hexo 博客根目录下创建 .github/workflows/deploy.yml,写入以下内容:
1 | name: Deploy Hexo Blog |
branches: master—— 你的 Hexo 源码分支,我用的是 master,如果你用 main 记得改submodules: true——这行非常重要 ,Butterfly 主题是以 submodule 方式引入的,不加这步主题文件不会被拉下来node-version: '20'—— 用 Node 20,稳定且是 LTS 版本cache: 'npm'—— GitHub 自带的 npm 缓存,比手动缓存node_modules方便npm ci—— 比npm install更快更严格,适合 CI 环境cname—— 自定义域名配置,会自动生成 CNAME 文件。没有自定义域名就删掉这行
方式二:使用官方 actions/deploy-pages
如果你更喜欢官方方案,配置如下:
1 | name: Deploy Hexo Blog |
使用方式二的话,需要去仓库 Settings → Pages → Source 里把 Source 改成 GitHub Actions,而不是选分支。否则部署会报错。
自定义域名 CNAME 处理
我的博客绑定了自定义域名 blog.jerryfage.top,这里有几个要注意的点:
如果用 peaceiris/actions-gh-pages:在
with里加cname: blog.jerryfage.top就行,它会自动在public/目录生成CNAME文件如果用官方 deploy-pages:需要在
source/目录下手动创建CNAME文件,内容就一行:blog.jerryfage.top。因为hexo generate会把source/下的所有文件复制到public/DNS 配置:在你的域名服务商那里,添加 CNAME 记录指向
jerry-fage.github.io
1 | # 在 Hexo 源码的 source 目录下创建 CNAME 文件 |
踩坑记录
坑一:GitHub Token 权限不足(403 错误)
用 peaceiris/actions-gh-pages 的时候,第一次部署大概率会遇到 403 错误。原因是 GITHUB_TOKEN 默认没有 contents: write 权限。
解决办法:在 workflow 的 jobs 下面加 permissions: contents: write,就像我上面的配置一样。
另外,第一次部署完成后,需要去仓库 Settings → Pages → Source 里手动选择 gh-pages 分支,不然 GitHub 不知道从哪里部署。
坑二:.gitignore 把 public/ 推上去了
有些同学的 .gitignore 里没有忽略 public/ 目录,结果把本地生成的文件也推到了远程。CI 环境会重新生成,这些本地产物反而会造成冲突。
检查一下你的 .gitignore,确保有这几行:
1 | public/ |
坑三:Butterfly 主题 Submodule 问题
这是最容易踩的坑。如果你的主题(比如 Butterfly)是用 git submodule 方式安装的,workflow 里必须加 submodules: true,否则 checkout 下来的代码里主题目录是空的,hexo generate 会直接报错。
有些同学用的是 npm install hexo-theme-butterfly 方式安装主题,这种不需要 submodules: true,因为你 npm ci 的时候主题就装好了。但如果你是 git submodule add 方式的,这行绝对不能少。
坑四:Node 版本不一致
本地用 Node 20,CI 里用 Node 16,生成结果可能不一样。建议 workflow 里固定一个 LTS 版本,目前推荐 Node 20。
完整流程总结
整个自动化部署流程就是这样的:
- 本地写文章,
hexo new "文章标题" - 写完
git add . && git commit -m "新文章" && git push - GitHub Actions 自动触发,拉代码、装依赖、生成静态页面、部署到 GitHub Pages
- 等两分钟,刷新博客就能看到新文章了
就这么简单,从此再也不用 hexo g && hexo d 了。




