建设过程中遇到的问题及解决


一、Node.js 环境问题

问题:终端没有激活 node 版本,hexo 命令无法执行。

source ~/.nvm/nvm.sh   # 激活 nvm
nvm list # 查看已安装版本
nvm use 20 # 选择版本
node -v && npm -v # 确认

二、文章封面默认设置未生效

问题_config.butterfly.ymldefault_top_img 路径没有生效。

# 错误
default_top_img: /source/images/top.jpg

# 正确(Hexo 约定:/images/ 自动指向 source/images/)
default_top_img: /images/top.jpg

三、双轨部署策略

博客维护两套独立的站点,共用一份源码,通过不同的部署方式发布:

正式站 备份站
GitHub 仓库 XianZe1226/XianZe1226.github.io XianZe1226/Blog_backup
网站地址 xianze1226.github.io xianze1226.github.io/Blog_backup/
部署方式 hexo deploy 手动推送 git push → GitHub Actions 自动部署
Pages 分支 main gh-pages

核心原理

两站共用 ~/BlogProject/Blog_backup 这一份 Hexo 源码,区别在于:

  • 正式站:本地 _config.ymlurl 设为 https://xianze1226.github.io,执行 hexo deploy 直接推送到正式站仓库。
  • 备份站git push 后 GitHub Actions 自动把 _config.yml 中的 url 覆盖为 https://xianze1226.github.io/Blog_backup,再构建部署到备份站的 gh-pages 分支。

这样两站的 URL 路径各自正确,互不干扰。

日常操作

# 改完内容后,发布到正式站
hexo clean && hexo generate && hexo deploy

# 同步到备份站(Actions 自动构建)
git add . && git commit -m "更新内容" && git push origin main

四、手动部署:内容不更新 / 404

问题:执行 hexo deploy 后网站没变化或文章 404。

原因:没清缓存,旧内容残留。

解决:每次部署必须三连:

hexo clean && hexo generate && hexo deploy

五、GitHub Actions 部署:CSS/JS 全部丢失,页面布局错乱

问题:Actions 部署成功,但网站没有样式、没有交互,布局完全错乱。

排查后发现三个原因:

原因 1:.gitignore 误排除

.gitignore 中加了 css/js/ 等规则,同时影响了 Actions 的部署流程。

解决.gitignore 只保留基础规则:

.DS_Store
Thumbs.db
db.json
*.log
node_modules/
public/
.deploy*/
_multiconfig.yml

原因 2:主题源文件未提交

themes/butterfly/source/ 目录(.styl.js 文件)没有被 git 跟踪,Actions 远端构建时找不到文件。

解决

git add themes/butterfly/source/
git commit -m "添加主题源文件"

原因 3:主题渲染器依赖缺失

hexo-renderer-stylushexo-renderer-pug 不在根目录 package.json 中。

解决

npm install hexo-renderer-stylus hexo-renderer-pug --save

完整 Actions workflow

文件路径:.github/workflows/deploy.yml

name: Deploy Hexo to GitHub Pages

on:
push:
branches:
- main

permissions:
contents: write

jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install dependencies
run: npm install

- name: Override config for backup site
run: |
sed -i 's|url: https://xianze1226.github.io|url: https://xianze1226.github.io/Blog_backup|' _config.yml
sed -i 's|href="/css/custom.css"|href="/Blog_backup/css/custom.css"|' _config.butterfly.yml

- name: Clean and Generate
run: npx hexo clean && npx hexo generate

- name: Deploy to gh-pages
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: public
clean: true

其中 Override config for backup site 这一步用 sed 把 URL 改为备份站路径,确保生成的静态文件中所有链接指向正确。

GitHub 仓库设置

Settings → Pages → Source → 选择 gh-pages 分支,文件夹选 / (root)

总结:Actions 部署出问题,99% 是文件没提交全或 .gitignore 排多了。检查 git ls-tree HEAD themes/butterfly/source/ 是否有输出,检查 .gitignore 是否有 css/js/ 等排除规则。


六、正式站部署后内容不更新

问题hexo clean && hexo generate && hexo deploy 三连正常跑完,终端没有红色报错,但访问网站仍然是旧内容。

这个问题有两个可能的原因,需逐一排查。


原因 1:.deploy_git 与远程仓库分叉,推送被拒

这是最常见也最隐蔽的原因。

原理hexo deploy 在本地维护一个 .deploy_git/ 目录,每次把 public/ 的文件拷进去、git commit、再 git push 到远程正式站仓库。

如果有人手动在 Blog_pages/ 目录或者直接在 GitHub 网页上向正式站仓库提交了内容,远程就会多出一个 .deploy_git/ 本地没有的 commit。此时 hexo deploy 的推送会因 non-fast-forward 被 git 拒绝,但 Hexo 不会把这个错误显眼地报出来,终端看起来像成功了。

诊断方法——对比两边 git 历史:

# .deploy_git 本地最新
cd Blog_backup/.deploy_git && git log --oneline -3

# 远程最新(通过 Blog_pages 查看)
cd Blog_pages && git pull origin main && git log --oneline -3

如果两边 HEAD 不一致,比如:

.deploy_git:  7c9d65a (最新生成)
829763c (共同祖先)
Blog_pages: 12d79bf (手动提交)
829763c (共同祖先)

说明出现了分叉,hexo deploy 的推送实际失败了。

解决

rm -r Blog_backup/.deploy_git
cd Blog_backup
hexo clean && hexo generate && hexo deploy

删除分叉的 .deploy_git/,让 hexo deploy 重新初始化仓库并推送。

预防:不要手动修改 Blog_pages/ 目录,也不要在 GitHub 网页上直接编辑正式站仓库。所有修改都走 Blog_backup → hexo deploy 这条链路。


原因 2:缺少 .nojekyll 文件

GitHub Pages 默认会用 Jekyll 处理所有仓库文件。对于 Hexo 生成的纯静态 HTML,需要放置一个空的 .nojekyll 告诉 GitHub Pages 跳过 Jekyll 处理,否则可能导致页面不更新、以 . 开头的目录被忽略。

注意:不能手动在 Blog_pages/ 里添加 .nojekyll——这正好会触发原因 1 的分叉问题。

正确的做法是写一个 Hexo 脚本,在 hexo generate 阶段自动生成:

// scripts/nojekyll.js
const fs = require('fs')
const path = require('path')

hexo.extend.filter.register('after_generate', function () {
const dir = hexo.public_dir
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true })
}
const f = path.join(dir, '.nojekyll')
if (!fs.existsSync(f)) {
fs.writeFileSync(f, '')
hexo.log.info('.nojekyll created in public/')
}
})

hexo.extend.filter.register('before_deploy', function () {
const deployDir = path.join(hexo.base_dir, '.deploy_git')
const nojekyllDest = path.join(deployDir, '.nojekyll')
if (fs.existsSync(deployDir)) {
fs.writeFileSync(nojekyllDest, '')
hexo.log.info('.nojekyll copied to .deploy_git/')
}
})

关键点:after_generate 中必须先检查 public/ 目录是否存在再写入,否则 hexo clean 后首次生成会因目录不存在而报 ENOENT 错误。


总结排查顺序

  1. 先查原因 1:对比 .deploy_gitBlog_pages 的 git 历史是否一致
  2. 再查原因 2:确认 public/.nojekyll 和远程仓库 .nojekyll 是否存在
  3. 部署后等 1-2 分钟(GitHub Pages 构建延迟),刷新确认

七、图库:Butterfly 画廊 + jsDelivr CDN

问题:footer 图库直接链接到 GitHub 仓库,没有预览,体验粗糙。

方案

利用 Butterfly 内置的 {% gallery %} 标签,在站内创建瀑布流画廊。图片托管在 GitHub 图床(XianZe1226/img_bed),通过 jsDelivr CDN 加速加载。

页面配置

# source/photo/index.md
---
title: 图库
type: 'photo'
comments: false
---

> 图片托管于 GitHub 图床,通过 jsDelivr CDN 加速加载。

{% gallery %}
![](https://cdn.jsdelivr.net/gh/XianZe1226/img_bed@main/photo1.jpg)
![](https://cdn.jsdelivr.net/gh/XianZe1226/img_bed@main/photo2.jpg)
{% endgallery %}

画廊效果

  • 瀑布流自适应排版(justified gallery)
  • 点击图片灯箱放大,可左右翻看
  • 图片通过 jsDelivr CDN 加载,速度远比 GitHub 裸链快

后续添加图片的步骤

  1. 上传新图片到 GitHub 图床仓库
  2. 拼出 jsDelivr CDN 地址:https://cdn.jsdelivr.net/gh/XianZe1226/img_bed@main/文件名
  3. source/photo/index.md{% gallery %} 块中新增一行 ![](CDN地址)
  4. 执行 hexo clean && hexo generate && hexo deploy 部署

_config.butterfly.yml 中将图库链接从 GitHub 裸链改为站内页面:

- title: 图库
url: /photo/

八、项目维护:锁文件、Node 版本与部署边界

问题:项目在本地长期迭代后,容易同时留下多个包管理器锁文件、生成产物、部署缓存和系统临时文件。它们不一定会立刻导致网站故障,但会让之后排查问题变复杂。

维护原则

当前双轨部署策略是正确的:

  • Blog_backup/ 是唯一源码仓库,文章、主题配置、脚本都在这里维护。
  • 正式站 XianZe1226.github.io 只通过 hexo deploy 更新。
  • 备份站 Blog_backup 只通过 git push origin main 触发 GitHub Actions 构建。
  • 不手动修改 Blog_pages/,避免 .deploy_git 与正式站远程历史分叉。

包管理器统一

项目实际使用 npm:

  • GitHub Actions 使用 npm install
  • README 使用 npm install
  • 依赖锁定以 package-lock.json 为准

因此删除 pnpm-lock.yaml,并在 .gitignore 中忽略它,避免之后误以为项目要用 pnpm。

Node 版本固定

新增 .nvmrc

20

以后进入项目后执行:

source ~/.nvm/nvm.sh
nvm use

nvm 会自动读取 .nvmrc 并切到 Node 20。这样本地环境与 GitHub Actions 的 node-version: '20' 保持一致。

生成产物边界

以下目录只作为本地运行或部署缓存,不作为源码维护:

node_modules/
public/
.deploy*/
db.json

Blog_pages/ 里如果出现 .DS_Store 之类未跟踪文件,不要为了清理它去手动提交正式站仓库。正式站目录应继续由 hexo deploy 管理。

发文章脚本说明修正

new-post.sh 会从 source/images/ 中选择当前已有的最大数字编号图片作为封面。这样至少能保证生成的文章默认封面存在,不会因为自动写入还没准备好的 /images/6.jpg 之类路径而断图。

如果要给新文章使用独立封面,先把图片放进 source/images/,再手动改文章 front matter 里的 cover