Hexo 8 + Keep 4 部署到 Cloudflare Pages:GitHub、自定义域名与 DNS
本文记录金猪博客当前实际使用的发布架构:在本地用 Hexo 生成静态文件,通过 Git 推送到 GitHub,再由 Cloudflare Pages 发布到自定义域名。除了基础部署,还会处理 SSH 端口受限、DNS、重复收录、缓存、安全响应头以及发布前检查。
本文于 2026-07-29 使用 Hexo 8.1.2、Keep 4.3.0 和 Node.js 22 验证。软件要求会变化,安装时应同时查看文末官方文档。
1. 先选择部署架构
Hexo 的源文件和生成网站是两种不同的东西:
- 源文件:Markdown、主题配置、插件和
package.json。 - 生成网站:
public/中的 HTML、CSS、JavaScript 和图片。
Cloudflare Pages 可以采用两种部署方式。
方式 A:Cloudflare Pages 构建 Hexo 源码
1 | Markdown 源码 |
这种方式自动化程度高,适合把完整源码安全地保存到 GitHub。Cloudflare Pages 的构建命令填写:
1 | npm ci && npm run build |
构建输出目录填写:
1 | public |
方式 B:本地生成后推送静态仓库
金猪博客目前采用这种方式:
1 | Markdown 源码 |
Cloudflare 连接的仓库已经是生成后的静态网站,因此不再执行 Hexo 构建。Pages 项目选择“无框架”,Build command 留空,输出位置使用仓库根目录。
两种方式都可以工作,但不要混用:如果 GitHub 仓库只有生成文件,Cloudflare 就不能执行 npm run build;如果仓库保存的是 Hexo 源码,Pages 的输出目录就应指向 public。
2. 安装 Hexo 与 Keep
先检查 Node.js、npm 和 Git:
1 | node --version |
创建新博客:
1 | npm install --global hexo-cli |
安装 Keep 主题:
1 | npm install hexo-theme-keep --save |
然后在 _config.yml 中启用:
1 | theme: keep |
已有项目应优先使用仓库里的锁文件恢复依赖:
1 | npm ci |
不要只依赖全局安装的 Hexo 版本。项目内依赖和 package-lock.json 能让本地与构建服务器得到更一致的结果。
3. 配置正式域名
至少检查 _config.yml 中这些项目:
1 | title: 金猪博客 |
url 必须写最终正式域名。它会影响 canonical、站点地图、RSS 和主题生成的绝对地址。如果这里仍是 pages.dev 或 github.io,搜索引擎可能把备用域名视为主版本。
language: en 控制 Keep 的导航和界面语言,不妨碍正文使用中文。
4. 本地生成与预览
清理缓存并生成网站:
1 | npm.cmd run clean |
在 Windows PowerShell 中,如果执行 npm 时出现“禁止运行脚本”的提示,可以直接使用 npm.cmd,不必为了运行博客而永久放宽整个系统的执行策略。
启动本地服务器:
1 | npm.cmd run server |
然后访问 http://localhost:4000/,重点检查:
- 首页和文章能否打开;
- Tags、Categories 和 Archives 是否有内容;
- 图片、代码块和站内链接是否正常;
- 移动端菜单和深色模式是否可用。
5. 配置 Git 一键部署
安装部署插件:
1 | npm install hexo-deployer-git --save |
在 _config.yml 中配置生成站仓库:
1 | deploy: |
ignore_hidden: false 很重要。如果网站需要发布 .well-known/security.txt 或 .nojekyll,部署器的默认隐藏文件过滤可能让本地构建正常、线上文件却消失。
标准三件套是:
1 | npm.cmd run clean |
本站进一步组合成一个发布命令:
1 | { |
以后只需运行:
1 | npm.cmd run release |
predeploy 会在推送前检查断链、canonical、JSON-LD、站点地图以及 Tags/Categories 是否意外变空。检查失败时终止部署,比上线后才发现空页面安全得多。
如果对 Git 尚不熟悉,可以先阅读本站的 Git 使用教程。
6. SSH 端口 22 不通时改用 443
部分公司、校园或受限网络会拦截 SSH 默认端口 22。这时可能看到:
1 | ssh: connect to host github.com port 22: Connection timed out |
GitHub 官方支持通过 HTTPS 端口建立 SSH 连接。先测试:
1 | ssh -T -p 443 [email protected] |
注意端口 443 使用的主机名是 ssh.github.com,不是 github.com。仓库地址可直接写成:
1 | ssh://[email protected]:443/USERNAME/REPOSITORY.git |
第一次连接前应核对 GitHub 公布的主机密钥指纹,不要未经确认接受陌生指纹。
7. 创建 Cloudflare Pages 项目
进入 Cloudflare 控制台:
- 打开 Workers & Pages。
- 选择 Create application → Pages → Connect to Git。
- 授权并选择 GitHub 仓库。
- 设置生产分支,例如
main。 - 根据前面选择的部署架构填写构建设置。
- 保存并等待第一次部署完成。
如果连接的是 Hexo 源码仓库:
1 | Build command: npm ci && npm run build |
如果连接的是已经生成的静态仓库:
1 | Framework preset: None |
Cloudflare Git 集成会把生产分支部署到项目的 *.pages.dev 地址,其他分支可以生成预览部署。
8. 绑定自定义域名和 DNS
不要只在 DNS 页面手动添加 CNAME。应先进入:
1 | Workers & Pages |
把 dajinzhu.cn 这类根域名绑定到 Pages 项目。根域名需要位于同一个 Cloudflare 账户并使用 Cloudflare 名称服务器,Cloudflare 会处理 CNAME Flattening 和证书签发。
子域名的典型记录是:
1 | 类型: CNAME |
如果使用根域名,可以在 Pages 完成自定义域名关联后,让 Cloudflare 自动创建或确认相应记录。仅创建 DNS 记录却没有在 Pages 项目中关联域名,可能导致解析失败或 522。
邮件的 MX、SPF、DKIM 等记录与网站记录是不同用途。修改网站 CNAME 时不要删除邮件记录,也不要让 MX 记录经过 Cloudflare 代理。
9. 避免备用域名重复收录
正式域名上线后,PROJECT.pages.dev 仍可能直接访问。至少要保证搜索引擎不会把两个域名都收录。
本站在 source/_headers 中设置:
1 | https://PROJECT.pages.dev/* |
更彻底的方案是在 Cloudflare 使用 Bulk Redirect,把 *.pages.dev 以 301 跳转到正式域名,并保留路径和查询参数。
同时确保每个页面的 canonical 指向:
1 | <link rel="canonical" href="https://dajinzhu.cn/..."> |
10. 缓存与安全响应头
Cloudflare Pages 支持在输出目录放置 _headers 文件。基础安全头可以这样配置:
1 | /* |
对没有内容哈希的 CSS 和 JavaScript,不建议直接设置一年 immutable,否则修改文件后浏览器可能继续使用旧版本。本站采用较短的浏览器缓存:
1 | /css/* |
站点地图使用较短缓存,便于新文章被及时发现。遇到“GitHub 已更新但域名还是旧内容”时,应先比较 pages.dev 回源和正式域名,再判断是 Pages 构建延迟、浏览器缓存还是 Cloudflare 缓存。
11. SEO 发布基线
一个可被稳定抓取的 Hexo 博客至少应具备:
- 正确的正式域名
url; - 每页唯一 canonical;
- 独立标题和 description;
robots.txt;- XML sitemap;
- RSS/Atom;
- Open Graph;
BlogPostingJSON-LD;- 自定义 404;
- Tags 和 Categories 聚合页;
- 旧 URL 的 301 重定向。
robots.txt 示例:
1 | User-agent: * |
技术配置完成后,还应在 Google Search Console 和百度搜索资源平台提交站点地图。SEO 的后续增长主要来自持续发布、内部链接和旧文章维护,而不是不断堆叠插件。
12. 常见故障
Tags 和 Categories 页面是空的
Keep 4.3.0 会根据页面标题识别聚合模板。页面标题应分别为:
1 | title: Tags |
1 | title: Categories |
如果只写中文标题“标签”或“分类”,它们可能被当作普通页面渲染。
本地有 .well-known,线上却是 404
检查:
1 | deploy: |
还要确认生成仓库中确实提交了 .well-known/security.txt,不能只检查本地 public/。
部署成功但 Cloudflare 没有更新
依次确认:
- Hexo deploy 是否真的推到了 Pages 监听的生产分支;
- Cloudflare Pages 的最新部署是否对应新提交;
pages.dev是否已经显示新内容;- 自定义域名是否仍返回缓存;
- DNS 是否指向正确的 Pages 项目。
标签大小写造成重复或旧地址失效
AI、ai 和 Ai 可能生成不同路径,而 Windows 文件系统又不区分大小写。标签命名应统一;已经被收录的旧路径应配置 301,而不是直接让它变成 404。
总结
Hexo、GitHub 和 Cloudflare Pages 的组合并不复杂,真正容易出错的是“源码仓库与生成仓库混淆”“正式域名未写入配置”“备用域名重复收录”“隐藏文件未部署”以及“发布后没有自动检查”。
先明确部署架构,再把清理、生成、检查和推送固定成一个可重复命令。这样每次写完 Markdown 后,发布就不再是一串临时操作,而是一条可以验证、可以回退的工程流程。