这个博客从 2023 年 4 月之后就没再动过,依赖还停留在 Hexo 6.3.0 + Node 12 + gulp 4。最近借着「升级依赖 + 修复潜在问题」的机会做了一次完整清理,中间踩了不少坑,记录下来方便以后回看,也给遇到同类问题的朋友一个参考。

说明:本次升级从诊断、升级到修复全程由 DeepSeek Harness 辅助完成。因为博客停更太久,依赖老化、配置过时、密钥泄露等问题成堆,整个排查和处理过程基本是全自动跑完的,我主要负责关键决策和最终发布。

升级前先诊断,发现这些问题

升级不是简单改个版本号。动手之前先把整个项目扫了一遍,发现的问题比想象中多:

  1. 部署脚本其实早就坏了。gulpfile.js 里写的是 gulp 3 的数组语法 gulp.task('hexo', ['minify-html', 'minify-css']),但实际装的是 gulp 4,gulp hexo 会直接报 Task function must be specified。也就是说 npm run deploy 一直是废的。
  2. 构建报废弃警告。_config.yml 里 external_link: true 是布尔值,Hexo 提示应该改成对象形式。
  3. 部署器缺失。_config.yml 的 deploy 配了 baidu_url_submitter,但插件根本没装,hexo deploy 会报 Deployer not found。
  4. 模板残留调试代码。主题 index.ejs 里留了一行 console.log(post.tags),每次构建都往外刷几千行对象日志。
  5. 配置笔误。word_count: ture(ture 拼错)、plugins: 块格式错误(Hexo 压根不读它)。
  6. 安全隐患。旧评论系统 Gitment 的 OAuth client_secret 被写进了页面内联 JS,等于把密钥公开暴露在网页上。
  7. 信息泄露。source/ 目录下残留一个 82KB 的 debug.log(2018 年的调试日志,含本机路径和主机名),会被一起发布到站点根目录。
  8. Hexo 8 挂死的根因。hexo-migrator-wordpress 依赖的 camaro 用了 worker_threads,导致 hexo generate 跑完后进程不退出(MessagePort 没关)。

升级清单

先确认了各依赖在 npmmirror 上的最新版本,然后一次性重写了 package.json:

组件旧版本新版本
Node12.16.322.20.0
hexo6.3.08.1.2
gulp4.0.25.0.1
渲染/生成器全系旧最新

同时做了这些事:

  • 删僵尸依赖:help、to、update、npm、npm-check、npm-upgrade、gulp-strip-debug、gulp-uglify 等一堆没用的包。
  • 删 hexo-migrator-wordpress:解决上面第 8 条挂死问题(这个 migrator 已经用不上了)。
  • 重写 gulpfile.js:改成 gulp 5 的 gulp.series(),压缩 HTML 换成 gulp-html-minifier-terser,压缩 CSS 换成 gulp-clean-css。
  • 补装 hexo-baidu-url-submit:让百度推送部署器能正常注册。

gulp-html-minifier-terser 最新 8.x 要求 Node 24,所以这里用了 7.1.0 兼容 Node 22。

Node 环境的处理

系统自带的 Node 是 12,但 Hexo 8 要求 Node ≥ 20.19。本来想用 Homebrew 装 node@22,结果这台机器 brew 的缓存目录权限有问题一直装不上,最后改成项目内独立 Node:把 Node 22.20.0 解压到项目的 .node/ 目录,用的时候把它的 bin 提到 PATH 前面。

这样有个好处:不影响系统其他环境,这个博客用 Node 22,别的地方继续用系统 Node 12,互不干扰。代价是每次构建前要手动 export 一下,或者干脆在 ~/.zshrc 里加个 chpwd 钩子,cd 进这个目录自动切换、cd 出去自动还原。

评论系统:Gitment → giscus

换掉 Gitment 主要有两个原因:

  1. 安全:Gitment 需要把 OAuth client_secret 写进前端页面,这是硬伤,密钥等于公开。
  2. 维护:Gitment 已经很久没更新了,GitHub 侧的授权也经常出问题。

替换方案选了 giscus,它用 GitHub Discussions 当评论后端,不需要自己暴露任何密钥,只需要公开的 repo_id 和 category_id。

配置步骤就三步:

  1. 仓库开启 Discussions(Settings → General → Features)。
  2. 安装 giscus app,授权仓库。
  3. 到 giscus.app 填仓库名,拿到 repo_id、category_id 回填到 _config.yml 的 comment 块。

改完之后模板里的守卫条件是「giscus 且 repo_id 非空才渲染」,这样 ID 没填之前页面不会出现坏掉的评论区。

部署遇坑:SSH 密钥被 GitHub 拒了

构建、压缩都通了之后,hexo deploy 卡在推送:

1
git@github.com: Permission denied (publickey).

排查下来,机器上只有一把 2015 年的 2048 位 RSA 密钥。把它加到 GitHub 时,GitHub 直接拒绝:

Key is too short. GitHub recommends using ssh-keygen to generate a RSA key of at least 3072 bits.

GitHub 现在不接受 2048 位 RSA 了。解决办法是换 Ed25519:

1
ssh-keygen -t ed25519 -C "you@example.com" -f ~/.ssh/id_ed25519 -N ""

然后把新公钥加到 GitHub,再配一下 ~/.ssh/config 让 GitHub 连接只走新密钥:

1
2
3
4
5
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes

ssh -T git@github.com 返回 Hi xxx! You've successfully authenticated 就通了,重新 npm run deploy 即可。

总结

这次升级本质上是「把 3 年没动的项目救回来」:

  • 依赖:Hexo 6 → 8,Node 12 → 22,gulp 3 → 5,全部生成器/渲染器升级到最新。
  • 修复:部署脚本、废弃配置、拼写错误、模板调试代码、挂死问题。
  • 安全:换掉泄露密钥的 Gitment,删掉会被发布的 debug.log。
  • 新功能:giscus 评论、百度 URL 推送。

如果你也在维护一个很久没动的 Hexo 博客,建议重点检查三件事:gulpfile.js 的 gulp 版本语法、_config.yml 里被弃用的布尔配置、以及评论插件是否把密钥写进了前端。这三样是重灾区。