六维教程

Hexo 钩子生命周期

Hexo 提供了两种钩子机制来让开发者介入博客的构建流程:事件(Events)过滤器(Filters)。本文将按照执行顺序,逐一讲解所有钩子,并注明哪些是特定命令所独有的。

两种钩子机制概览

事件(Events)

Hexo 继承了 Node.js 的 EventEmitter,你可以通过 hexo.on() 方法监听事件,通过 hexo.emit() 方法触发事件。

// 监听事件示例
hexo.on('generateBefore', function () {
  console.log('生成即将开始...');
});

过滤器(Filters)

过滤器用于修改特定的数据,Hexo 将数据按顺序传递给过滤器,过滤器逐个修改数据。注册方式为:

hexo.extend.filter.register('过滤器名称', function (data) {
  // 修改 data
  return data;
}, priority);

priority 值越低,执行越早,默认为 10。

钩子执行顺序

第一阶段:初始化

顺序 钩子类型 名称 触发时机
1 事件 ready Hexo 初始化完成后触发。
2 过滤器 after_init Hexo 初始化完成后执行(紧随 hexo.init 完成之后)。

这是所有命令都会经过的入口阶段。ready 事件和 after_init 过滤器在功能上类似,都在初始化完成后触发。

第二阶段:处理源文件(Processing)

这个阶段 Hexo 会扫描并处理 source 文件夹中的源文件(如 Markdown 文章)。

顺序 钩子类型 名称 触发时机
3 事件 processBefore 开始处理原始文件前触发。此事件返回一个路径,代表 Box(源文件目录)的根目录。
4 过滤器 post_permalink 用于确定文章的永久链接(Permalink)。
5 过滤器 before_post_render 每篇文章开始渲染前执行。
6 (内置渲染) Markdown/渲染器渲染 使用 Markdown 或其他渲染器进行渲染(取决于扩展名)。
7 (内置渲染) Nunjucks 渲染 使用 Nunjucks 模板引擎渲染。
8 过滤器 after_post_render 每篇文章渲染完成后执行。
9 事件 processAfter 所有原始文件处理完成后触发。此事件返回一个路径,代表 Box 的根目录。

注意before_post_renderafter_post_render 是针对每篇文章逐个执行的,而不是只执行一次。

第三阶段:生成静态文件(Generation)

这个阶段 Hexo 的生成器(Generator)会创建静态 HTML 文件。

顺序 钩子类型 名称 触发时机
10 事件 generateBefore 在生成器开始工作前触发。
11 过滤器 before_generate 在生成过程开始前执行。
12 过滤器 template_locals 修改模板的局部变量(在生成路由后、渲染模板前)。
13 (内置) 模板渲染 Hexo 使用模板引擎渲染生成最终的 HTML 页面。
14 过滤器 after_render 在每次渲染完成后执行。这是一个过滤器家族,可以根据输出格式细分为多种类型:
after_render:html — 处理 HTML 文件
after_render:css — 处理 CSS 文件
after_render:js — 处理 JavaScript 文件
after_render:xml — 处理 XML 文件(如 Sitemap)
注册时需指定具体格式,如 hexo.extend.filter.register('after_render:html', fn)
15 事件 generateAfter 在生成器工作完成后触发。
16 过滤器 after_generate 在生成完成后执行。

说明

  • hexo generatehexo server 在启动阶段都会完整经历上述第 10-16 步。
  • after_render 过滤器会在每一次渲染完成后执行,不仅仅是在最终页面生成时。这意味着它也可能在渲染文章摘要、主题的局部模板(如侧边栏)等场景下被触发。如果你的逻辑只需在完整页面上生效,需要通过 data 参数中的上下文信息(如 data.layout)进行判断。

第四阶段:特有行为

hexo generate

顺序 钩子类型 名称 触发时机 适用命令
17 过滤器 before_exit 在 Hexo 即将退出时执行(紧随 hexo.exit 被调用之后)。 hexo generatehexo server(手动停止时)
18 事件 exit 在 Hexo 进程退出前触发。 hexo generatehexo server(手动停止时)

hexo generate 在生成完静态文件后会立即退出,因此第 17-18 步会在生成完成后马上触发。

hexo server

顺序 钩子类型 名称 触发时机 适用命令
17 过滤器 server_middleware 添加中间件到服务器。此钩子由 hexo-server 提供,非 Hexo 核心,仅在安装 hexo-server 时运行。 hexo server 独有
18 (内置) 启动服务器 Hexo 启动 Web 服务器,在控制台输出本地访问地址(如 http://localhost:4000),并持续监听文件变化。 hexo server 独有
19 过滤器 before_exit 在 Hexo 即将退出时执行(手动停止服务器时,如按 Ctrl+C)。 hexo server 独有(手动停止时)
20 事件 exit 在 Hexo 进程退出前触发(手动停止服务器时)。 hexo server 独有(手动停止时)

关键区别

  • hexo generate:生成后直接退出,触发 before_exit / exit
  • hexo server:生成后保持运行before_exit / exit 在手动停止时才触发
  • server_middlewarehexo server 独有的钩子

其他独立钩子

以下钩子不属于上述主流程,但在特定场景下会被触发:

钩子类型 名称 触发时机 适用命令
事件 new 通过 hexo new 命令成功创建新文章后触发。返回 post.path(完整路径)和 post.content(内容)。 hexo new 独有
过滤器 new_post_path 创建新文章时,用于决定新文章的保存路径。 hexo new 独有
事件 deployBefore 在部署开始前触发。 hexo deploy 独有
事件 deployAfter 在部署完成后触发。 hexo deploy 独有
过滤器 after_clean hexo clean 命令移除生成文件和缓存后执行。 hexo clean 独有
过滤器 router 在渲染路由之前修改路由数据。此过滤器可用于添加、删除或修改路由。 所有命令

钩子使用示例

监听事件

在 Hexo 根目录的 scripts/ 文件夹中创建脚本文件:

// scripts/my-hooks.js
hexo.on('ready', function () {
  console.log('✅ Hexo 已就绪!');
});

hexo.on('generateBefore', function () {
  console.log('⏳ 开始生成静态文件...');
});

hexo.on('generateAfter', function () {
  console.log('✅ 生成完成!');
});

hexo.on('exit', function () {
  console.log('👋 Hexo 进程即将退出');
});

注册过滤器

// scripts/my-filters.js
// 在文章渲染前将标题转为小写
hexo.extend.filter.register('before_post_render', function (data) {
  data.title = data.title.toLowerCase();
  return data;
}, 10);

// 在文章渲染后替换内容中的 @用户名 为 Twitter 链接
hexo.extend.filter.register('after_post_render', function (data) {
  data.content = data.content.replace(
    /@(\w+)/g,
    '<a href="https://twitter.com/$1">@$1</a>'
  );
  return data;
}, 10);

// 在生成前执行自定义逻辑
hexo.extend.filter.register('before_generate', function () {
  console.log('⏳ 生成前执行自定义逻辑...');
});

// 修改模板局部变量
hexo.extend.filter.register('template_locals', function (locals) {
  locals.currentYear = new Date().getFullYear();
  return locals;
});

// 压缩 HTML(使用 after_render:html)
const htmlMinifier = require('html-minifier');
hexo.extend.filter.register('after_render:html', function (str, data) {
  // str: 渲染完成后的 HTML 字符串
  // data: 包含页面相关信息的对象
  // 注意:此过滤器会在每次渲染完成后执行,不仅限于完整页面
  // 可以通过 data.layout 判断是否为完整页面
  if (data.layout && data.layout !== 'false') {
    return htmlMinifier.minify(str, {
      removeComments: true,
      collapseWhitespace: true,
      minifyJS: true,
      minifyCSS: true
    });
  }
  return str;
}, 10);

过滤器优先级

优先级数字越小,执行越早:

// 优先执行(priority: 1)
hexo.extend.filter.register('after_post_render', function (data) {
  // 最先执行
  return data;
}, 1);

// 后执行(priority: 20)
hexo.extend.filter.register('after_post_render', function (data) {
  // 最后执行
  return data;
}, 20);

快速参考表

阶段 钩子名称 类型 hexo g hexo s hexo d hexo new hexo clean
初始化 ready 事件
初始化 after_init 过滤器
处理源文件 processBefore 事件
处理源文件 post_permalink 过滤器
处理源文件 before_post_render 过滤器
处理源文件 after_post_render 过滤器
处理源文件 processAfter 事件
生成 generateBefore 事件
生成 before_generate 过滤器
生成 template_locals 过滤器
生成 after_render(及 :html 等变体) 过滤器
生成 generateAfter 事件
生成 after_generate 过滤器
生成 router 过滤器
服务器 server_middleware 过滤器 ✅ 独有
部署 deployBefore 事件 ✅ 独有
部署 deployAfter 事件 ✅ 独有
新建文章 new 事件 ✅ 独有
新建文章 new_post_path 过滤器 ✅ 独有
清理 after_clean 过滤器 ✅ 独有
退出 before_exit 过滤器 ✅(手动停止)
退出 exit 事件 ✅(手动停止)

总结

  1. 事件(Events)过滤器(Filters) 是 Hexo 提供的两种钩子机制,分别用于监听流程节点和修改数据。
  2. 核心流程:所有构建命令(generateserver)都会经历 初始化 → 处理源文件 → 生成静态文件 三个阶段。
  3. 命令特有钩子
    • hexo server 独有 server_middleware 过滤器
    • hexo deploy 独有 deployBefore / deployAfter 事件
    • hexo new 独有 new 事件和 new_post_path 过滤器
    • hexo clean 独有 after_clean 过滤器
  4. after_render 过滤器家族after_render 本身是一个过滤器类型,可细分为 after_render:htmlafter_render:cssafter_render:jsafter_render:xml 等。注册时需指定具体格式,且该过滤器会在每次渲染完成后执行,不仅限于最终页面。
  5. 退出时机hexo generate 在生成完成后立即退出;hexo server 保持运行,直到手动停止才触发退出钩子。
上一篇
Hexo [_Document]
下一篇
Hexo hexo-admin插件