Hexo 博客部署到 Cloudflare Pages 完整流程

这篇文章记录一次将 Hexo 博客源码托管到 GitHub,并通过 Cloudflare Pages 自动构建、部署、绑定自定义域名的完整过程。

写这篇文章的背景也很简单:之前博客一直部署在阿里云服务器上,但服务器到期后,如果只是为了放一个静态博客,继续续费一台云服务器有点浪费。Hexo 本身生成的就是静态文件,而 Cloudflare Pages 免费额度已经足够个人博客使用,还自带 HTTPS、CDN、DNS 和基础安全防护,所以这次就把博客迁移到了 Cloudflare Pages。
最终效果是:每次本地写完文章后,只需要把代码推送到 GitHub,Cloudflare Pages 就会自动拉取代码、执行 Hexo 构建,并把博客发布到自己的域名上。

1. 整体原理

整个流程可以理解为:

Hexo 源码
-> GitHub 仓库
-> Cloudflare Pages 拉取代码
-> 执行 npx hexo generate
-> 生成 public 静态文件
-> Cloudflare 全球节点托管
-> 用户通过自定义域名访问

其中:

  • GitHub 负责保存 Hexo 博客源码。
  • Cloudflare Pages 负责自动构建和托管网站。
  • DNS 负责把自己的域名指向 Cloudflare Pages。
  • Cloudflare 负责 HTTPS、CDN 加速和基础安全防护。

2. 准备 Hexo 博客仓库

Hexo 项目中通常会包含这些文件和目录:

_config.yml
package.json
source/
themes/
scaffolds/

其中 source/_posts/ 保存博客文章,themes/ 保存主题,_config.yml 是 Hexo 的主配置文件。

建议 .gitignore 中排除这些内容:

node_modules/
public/
db.json
.deploy_git/

public/ 是 Hexo 构建后的产物,不需要提交到 GitHub。Cloudflare Pages 会在云端自动生成它。

3. 处理主题 submodule 问题

部署时最先遇到的问题是 Cloudflare Pages 报错:

Failed: error occurred while updating repository submodules

这个错误说明 Cloudflare 在拉取 GitHub 仓库时,尝试更新 Git submodule,但仓库里的子模块配置不完整或不可访问。

可以通过下面的命令检查:

git ls-files --stage | Select-String "160000"

如果看到类似:

160000 ... themes/hexo-theme-icarus
160000 ... themes/yilia

说明主题目录仍然被 Git 当成 submodule。

解决方法是把主题改成普通文件夹:

git rm --cached themes/hexo-theme-icarus
git rm --cached themes/yilia
git add themes/hexo-theme-icarus
git add themes/yilia
git commit -m "convert themes to normal folders"
git push

如果执行 git add themes/yilia 时出现:

warning: adding embedded git repository

说明主题目录内部还有自己的 .git 文件夹。需要删除主题内部的 .git

Remove-Item -Recurse -Force themes/yilia/.git
Remove-Item -Recurse -Force themes/hexo-theme-icarus/.git

注意:删除的是主题目录内部的 .git,不是博客项目根目录的 .git

4. 修复依赖安装问题

解决 submodule 后,Cloudflare 进入依赖安装阶段,又出现了错误:

Failed: error occurred while installing tools or dependencies

日志中关键部分是:

hexo-asset-image@https://github.com/CodeFalling/hexo-asset-image: Failed listing refs
Repository URL: ssh://git@github.com/CodeFalling/hexo-asset-image.git
Fatal Error: Could not read from remote repository.

原因是 package.json 中的 hexo-asset-image 依赖使用了 GitHub 地址,Cloudflare 构建时被解析成了 SSH 地址:

ssh://git@github.com/CodeFalling/hexo-asset-image.git

Cloudflare 构建环境没有我的 GitHub SSH 权限,所以无法拉取这个依赖。

一开始我尝试把它改成 npm 版本:

"hexo-asset-image": "^1.0.0"

这个版本虽然可以安装成功,但后面发现它会把文章图片路径处理错。我的域名是:

https://zwq-tech.xyz

npm 版本的 hexo-asset-image 会把 .xyz 误识别成路径的一部分,导致生成出来的图片地址变成:

/.xyz//xxx.png

而正确的文章图片路径应该类似:

/2026/06/02/cloudflare-pages-hexo-deploy/xxx.png

所以最终采用的方案是:继续使用 GitHub 版本的 hexo-asset-image,但把依赖地址写成明确的 HTTPS Git 地址,避免 Cloudflare/Yarn 把它解析成 SSH:

"hexo-asset-image": "git+https://github.com/CodeFalling/hexo-asset-image.git"

同时删除 yarn.lock,统一使用 npm 安装依赖:

Remove-Item yarn.lock
npm install
git add package.json package-lock.json
git add -u
git commit -m "use github version of hexo asset image"
git push

这样 Cloudflare Pages 会通过 HTTPS 拉取 GitHub 上的插件版本,不需要 SSH 权限,也能保留之前博客文章的图片路径处理方式,避免大面积修改旧文章。

5. 创建 Cloudflare Pages 项目

进入 Cloudflare 控制台:

Workers & Pages -> Create application

如果进入的是 Worker 创建页面,需要点击底部:

Looking to deploy Pages? Get started

从 Worker 创建页切换到 Pages

然后选择:

Import an existing Git repository

选择导入已有 Git 仓库

选择自己的 GitHub 仓库,例如:

zhaowenqi0614/my-hexo-blog

6. 配置构建命令

Cloudflare Pages 中 Hexo 的关键配置如下:

Build command: npx hexo generate
Build output directory: public
Root directory: /

如果页面中出现必填的:

Deploy command

说明进入了 Workers 部署流程,不是 Pages。Hexo 博客不需要填写 npx wrangler deploy

Pages 只需要构建出 public 目录,Cloudflare 会自动发布这个目录。

建议在环境变量中添加:

NODE_VERSION=20

Pages 构建配置

7. 部署成功

配置完成后,Cloudflare Pages 会自动执行:

拉取 GitHub 仓库
安装依赖
执行 npx hexo generate
发布 public 目录

部署成功后会得到一个默认域名,例如:

https://my-hexo-blog-v44.pages.dev

项目部署成功

之后每次更新博客,只需要:

git add .
git commit -m "update blog"
git push

Cloudflare Pages 会自动重新构建和发布。

8. 接入自定义域名

我的域名是:

zwq-tech.xyz

首先在 Cloudflare 中添加站点:

Websites -> Add a site -> Connect a domain

输入域名后选择免费套餐:

Free

选择 Cloudflare Free 套餐

9. 配置 DNS 记录

因为我希望主域名直接访问博客,所以将原来指向旧服务器的 A 记录删除:

A   zwq-tech.xyz       121.40.121.3
A www.zwq-tech.xyz 121.40.121.3

然后新增两条 CNAME:

CNAME   zwq-tech.xyz       my-hexo-blog-v44.pages.dev
CNAME www.zwq-tech.xyz my-hexo-blog-v44.pages.dev

代理状态保持:

Proxied

TTL 保持:

Auto

DNS 记录配置完成

10. 修改域名的 Nameserver

Cloudflare 会给出两个 nameserver,例如:

daisy.ns.cloudflare.com
donovan.ns.cloudflare.com

需要到域名注册商后台,将原来的 DNS 服务器改成 Cloudflare 提供的这两个。

例如在阿里云中,将当前 DNS 服务器从:

dns27.hichina.com
dns28.hichina.com

改成:

daisy.ns.cloudflare.com
donovan.ns.cloudflare.com

阿里云 DNS 服务器修改完成

修改后需要等待 Cloudflare 检测生效。通常几分钟到几小时,最长可能需要 24 到 48 小时。

当 Cloudflare 显示:

Your domain is now protected by Cloudflare

说明域名已经成功接入 Cloudflare。

域名已接入 Cloudflare

11. 在 Pages 中绑定自定义域名

域名接入 Cloudflare 后,进入 Pages 项目:

Workers & Pages -> my-hexo-blog-v44 -> Custom domains

添加:

zwq-tech.xyz

再添加:

www.zwq-tech.xyz

当状态变成:

Active
SSL enabled

说明自定义域名绑定成功。

Pages 自定义域名绑定成功

此时可以访问:

https://zwq-tech.xyz
https://www.zwq-tech.xyz

12. 修改 Hexo 配置

最后需要修改 Hexo 的 _config.yml,让博客生成的链接使用正式域名:

url: https://zwq-tech.xyz
root: /

然后提交推送:

git add _config.yml
git commit -m "update site domain"
git push

Cloudflare Pages 会自动重新部署。

13. 关于 hexo d

Cloudflare Pages 部署不依赖 Hexo 的 deploy 配置。

也就是说,Cloudflare Pages 使用的是:

GitHub push -> Cloudflare Pages 自动构建 -> 发布 public

hexo d 使用的是 _config.yml 里的:

deploy:
type: git
repo: ...
branch: master

所以两者是两条独立路线。

如果继续执行:

hexo d

它会按照 deploy 中配置的仓库或服务器进行部署,不会影响 Cloudflare Pages 的自动部署。

14. 总结

对个人博客来说,这种方案最大的好处是成本低、维护少。GitHub 负责保存源码,Cloudflare Pages 免费负责构建和托管,域名继续正常续费即可。相比继续维护一台服务器,不需要再关心 Nginx、SSL 证书续期、服务器安全和系统更新这些问题,更适合 Hexo 这类静态博客。
这次部署中主要完成了这些事情:

  1. 将 Hexo 源码提交到 GitHub。
  2. 将主题从 Git submodule 改成普通文件夹。
  3. 修复 Cloudflare 构建环境无法拉取 GitHub SSH 依赖的问题。
  4. 创建 Cloudflare Pages 项目,并配置 Hexo 构建命令。
  5. 将域名 zwq-tech.xyz 接入 Cloudflare。
  6. 配置 DNS,将主域名和 www 指向 Pages 项目。
  7. 在 Pages 中绑定自定义域名并启用 HTTPS。
  8. 修改 Hexo 的站点 URL 为正式域名。

最终形成的工作流是:

本地写文章
-> git push
-> Cloudflare Pages 自动构建
-> zwq-tech.xyz 自动更新

这样以后维护博客就非常简单了,只需要专注写文章,部署交给 Cloudflare Pages 自动完成。