这个博客从 2023 年 4 月之后就没再动过,依赖还停留在 Hexo 6.3.0 + Node 12 + gulp 4。最近借着「升级依赖 + 修复潜在问题」的机会做了一次完整清理,中间踩了不少坑,记录下来方便以后回看,也给遇到同类问题的朋友一个参考。
说明:本次升级从诊断、升级到修复全程由 DeepSeek Harness 辅助完成。因为博客停更太久,依赖老化、配置过时、密钥泄露等问题成堆,整个排查和处理过程基本是全自动跑完的,我主要负责关键决策和最终发布。
升级前先诊断,发现这些问题
升级不是简单改个版本号。动手之前先把整个项目扫了一遍,发现的问题比想象中多:
- 部署脚本其实早就坏了。
gulpfile.js里写的是 gulp 3 的数组语法gulp.task('hexo', ['minify-html', 'minify-css']),但实际装的是 gulp 4,gulp hexo会直接报Task function must be specified。也就是说npm run deploy一直是废的。 - 构建报废弃警告。
_config.yml里external_link: true是布尔值,Hexo 提示应该改成对象形式。 - 部署器缺失。
_config.yml的 deploy 配了baidu_url_submitter,但插件根本没装,hexo deploy会报Deployer not found。 - 模板残留调试代码。主题
index.ejs里留了一行console.log(post.tags),每次构建都往外刷几千行对象日志。 - 配置笔误。
word_count: ture(ture 拼错)、plugins:块格式错误(Hexo 压根不读它)。 - 安全隐患。旧评论系统 Gitment 的 OAuth
client_secret被写进了页面内联 JS,等于把密钥公开暴露在网页上。 - 信息泄露。
source/目录下残留一个 82KB 的debug.log(2018 年的调试日志,含本机路径和主机名),会被一起发布到站点根目录。 - Hexo 8 挂死的根因。
hexo-migrator-wordpress依赖的camaro用了 worker_threads,导致hexo generate跑完后进程不退出(MessagePort 没关)。
升级清单
先确认了各依赖在 npmmirror 上的最新版本,然后一次性重写了 package.json:
| 组件 | 旧版本 | 新版本 |
|---|---|---|
| Node | 12.16.3 | 22.20.0 |
| hexo | 6.3.0 | 8.1.2 |
| gulp | 4.0.2 | 5.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 主要有两个原因:
- 安全:Gitment 需要把 OAuth
client_secret写进前端页面,这是硬伤,密钥等于公开。 - 维护:Gitment 已经很久没更新了,GitHub 侧的授权也经常出问题。
替换方案选了 giscus,它用 GitHub Discussions 当评论后端,不需要自己暴露任何密钥,只需要公开的 repo_id 和 category_id。
配置步骤就三步:
- 仓库开启 Discussions(Settings → General → Features)。
- 安装 giscus app,授权仓库。
- 到 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 | Host github.com |
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 里被弃用的布尔配置、以及评论插件是否把密钥写进了前端。这三样是重灾区。
