前言

一个看起来人畜无害的命令, 实测能把人逼疯:

1
2
hexo clean
# 2000+ 个文件, 跑了 12 分钟还没删完, 看起来像死机

同样的活, 换个方式:

1
2
rm -rf public db.json
# 5 秒, 完事

差距超过百倍。 这不是个别机器的问题, 换 Node 版本、清缓存、重装依赖都改善有限。这篇把根因讲清楚, 并给出可直接抄的替代方案。

一、先量化: 到底慢多少

实测环境: Windows, 站点约 2000+ 个产物文件 (public 目录)。

操作耗时
hexo clean超过 12 分钟未完成 (放弃等待)
rm -rf public db.json + hexo generate删除约 5 秒, 构建正常

也就是说, hexo clean 的删除阶段慢到像假死: 没有报错、没有进度、CPU 占用也不高, 就是永远走不完。

二、根因: hexo-fs 的删除实现

hexo clean 做两件事: 清掉数据库缓存 db.json, 删掉 public 目录。问题出在删除这一步。

Hexo 的文件操作封装在 hexo-fs 里, 它的递归删除 (_rmdir()) 大致逻辑是:

  • 用 bluebird.map 遍历目录树逐个删除
  • 没有限制并发数 —— 几千个文件删除操作同时压进事件循环

Linux 上文件系统对此容忍度较高, 问题不明显。但 Windows 上文件句柄操作要经过系统级排队, 上千个并发句柄请求互相排队、互相等待, 每个 I/O 的延迟被放大, 表现就是整体”卡住”。

两个加重因素:

  1. 递归目录: 每层目录的删除依赖子项完成, 无序并发让父子操作的排队关系更乱
  2. Windows Defender 等实时扫描: 每个删除动作可能触发扫描钩子, 并发越多排队越长

验证方法很简单: 对着同样的目录树, 用系统原生删除命令和 hexo clean 各跑一次, 差距立现。

三、替代方案: 手动删, 然后 generate

Git Bash / Linux / macOS

1
rm -rf public db.json && hexo generate

rm 走系统调用按目录树批量删, 没有 JS 层的并发放大, 快得理所当然。

PowerShell (Windows 原生)

1
2
Remove-Item -Recurse -Force public, db.json
hexo generate

固化成 npm scripts (跨平台)

团队协作或 CI 环境建议用 rimraf, 三端通用:

1
2
3
4
5
6
{
"scripts": {
"clean": "rimraf public db.json",
"build": "npm run clean && hexo generate"
}
}
1
2
npm install rimraf --save-dev
npm run build

四、顺手澄清: db.json 和”什么时候才需要清缓存”

db.json 是 Hexo 的工作数据库, 缓存文章元数据、资源索引等。日常写文章根本不需要 hexo clean, 增量构建本来就是 Hexo 的设计。

真正需要清缓存的场景:

场景原因
改了站点/主题配置后行为诡异部分配置被缓存固化
升级 Hexo 或插件之后旧缓存结构和新版本不兼容
构建产物和预期不一致排除缓存脏数据的干扰
修改了插件/过滤器源码确保改动生效

定位构建问题时, “先清缓存再排查”是标准第一步, 完整的排查顺序可以看这篇: Hexo 构建失败排查: 缓存没清干净, 换个 Node 版本就报错的两个坑。

只是清缓存这一步, 用 rm -rf 代替 hexo clean 即可, 效果完全等价 —— 它们清的都是同两样东西。

小结

  1. hexo clean 在 Windows 上删几千个文件会假死级地慢, 根因是 hexo-fs 无并发限制的递归删除撞上 Windows 句柄排队
  2. 替代方案: rm -rf public db.json (或 PowerShell 的 Remove-Item -Recurse), 然后 hexo generate
  3. 跨平台项目把命令固化成 npm scripts, 用 rimraf 保证三端一致
  4. 日常写作不需要清缓存; 清缓存留给配置变更、依赖升级和排查问题的时候

一句话: 效果等价、速度差百倍, 没有理由继续等它。

参考链接: