Hexo 自动化部署进阶:私有源码 + 公开网页的双仓库架构

你是否担心过 Hexo 的源码(Markdown 原稿、配置文件、主题源码)直接公开在 GitHub 上会有风险?或者每次更换电脑都要重新配环境、拷文件?

今天分享一套**“双仓库”自动化部署方案**:将源码放在私有仓库,通过 GitHub Actions 自动生成网页并推送到公开的 Pages 仓库。

1. 为什么要用双仓库?

传统的 Hexo 部署方式通常是将源码和生成的 HTML 混在一起,或者只备份 HTML。双仓库架构有以下优势:

  • 安全性:私有仓库(Private)存放你的 Markdown 原稿和 _config.yml,保护敏感配置和未发布的草稿。
  • 云端备份:源码在云端,换电脑只需 git clone,无需担心环境丢失。
  • 全自动流水线:本地只需执行 git push,剩下的环境配置、依赖安装、静态生成、发布全部由 GitHub Actions 代劳。

2. 准备工作

  1. 私有仓库 (source):例如 hexo-source,存放 Hexo 完整目录。
  2. 公开仓库 (public):例如 yourname.github.io,开启 GitHub Pages 服务。
  3. Personal Access Token (PAT):在 GitHub Settings 生成一个 Token,并赋予 repo 权限。
  4. 仓库 Secret:在私有仓库的 Settings -> Secrets and variables -> Actions 中,添加名为 HEXO_DEPLOY_TOKEN 的 Secret,值为刚才生成的 PAT。
  5. 本地 _config.yml 的“去繁就简”:在传统的 Hexo 部署中,我们通常会在 _config.yml 底部配置繁琐的 deploy 参数。但在 GitHub Actions 方案中,为了安全和灵活,我们不再把 Token 或具体的仓库地址写死在配置文件里。

修改建议:

找到文件末尾的 deploy 部分,将其简化为最基础的格式。这样做可以防止本地执行 hexo d 时因为没有配置 SSH 而报错,同时也让配置文件更加通用。

# Deployment
# 这里的配置仅作为占位符,真正的部署地址和权限已由 GitHub Actions 接管
deploy:
type: git
repo: https://github.com/你的用户名/你的公开仓库名.git
branch: main

3. GitHub Actions 脚本实现

在私有仓库根目录下创建 .github/workflows/deploy.yml,填入以下代码:

name: Hexo Deploy

on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Source
uses: actions/checkout@v3
with:
submodules: true # 支持拉取 git 子模块主题

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20.x' # 适配最新 Hexo 版本
cache: 'npm'

- name: Install Dependencies
run: |
npm install -g hexo-cli
npm ci --legacy-peer-deps

- name: Deploy to Public Repo
env:
PERSONAL_TOKEN: ${{ secrets.HEXO_DEPLOY_TOKEN }}
run: |
git config --global user.name "你的用户名"
git config --global user.email "你的邮箱"

npx hexo clean
npx hexo generate

cd public
git init
git checkout -b main
git add .
git commit -m "Site updated by GitHub Actions: $(date)"
git push --force https://x-access-token:${PERSONAL_TOKEN}@[github.com/你的路径/你的项目.git](https://github.com/你的路径/你的项目.git) main

3. 常见问题

1. 为什么本地不报错,云端报错?

这是最让新手崩溃的地方。

  • 原因:本地的 node_modules 可能是长期增量安装形成的,甚至可能手动修改过。而 GitHub Actions 每次运行都是在一个完全纯净的虚拟环境中执行 npm install。如果你的 package-lock.json(锁文件)没有更新,或者在 package.json 里用了 ^ 导致云端自动下载了不兼容的新版本(如 ESM 版本的 strip-ansi),就会导致崩溃。
  • 解决方法
    1. 在本地确认配置了 overrides
    2. 在本地执行一次 npm install 以刷新 package-lock.json
    3. 务必将最新的 package-lock.json 提交到私有仓库。
    4. 在 Actions 脚本中使用 npm ci 严格执行同步安装。

2. src refspec main does not match any

这是 Git 在推送阶段报的错。

  • 原因:在 GitHub Actions 虚拟机里,当你执行 git init 时,Git 的默认分支名往往是 master(取决于虚拟机的 git 版本配置)。但由于我们的公开仓库(GitHub Pages)使用的是 main 分支,当你尝试执行 git push ... main 时,Git 在本地找不到叫 main 的内容可以推。
  • 解决方法:在 git init 之后,显式执行一行命令:
    git checkout -b main

3.优化 package.json (解决 ESM 报错)

在 Hexo 8.x 版本中,常会遇到 ERR_REQUIRE_ESM 报错。我们需要在 package.json 中强制指定兼容版本:

"overrides": {
"strip-ansi": "6.0.1"
}