HexoPress 已经不再只是一个 Electron 桌面应用。现在它支持两种运行模式:基于 Electron 的桌面版,以及基于 Fastify 的自托管 Web 版。两种模式共享同一套渲染层应用,也共享同一套面向 Hexo 的核心服务逻辑。
两种运行模式
Electron mode
桌面版仍然采用典型的 Electron 分层:
- 主进程:负责应用生命周期、Hexo 集成、文件系统操作和本地服务
- 预加载脚本:通过
window.site.*暴露安全桥接接口 - 渲染进程:负责界面本身
这种模式适合直接在本机选择博客目录并进行本地编辑。
Web mode
自托管 Web 版把 Electron 的 IPC 边界替换成了 HTTP 边界:
- Fastify 服务端:负责鉴权、API 路由和站点初始化
- 浏览器中的渲染层 SPA
- 同一套 Hexo / 文件系统服务:真正执行博客读写
这种模式适合需要远程访问,但又不想把博客管理交给第三方 SaaS 的场景。
共享服务层
无论在哪种运行模式下,HexoPress 的后端职责都基本一致:
- HexoAgent:加载 Hexo 数据、查询文章/分类/标签、读写内容
- FsAgent:受控地访问
source/目录 - 资源预览与元数据能力:用于图片预览、文件信息读取和引用追踪
架构上的关键点在于:业务能力不是按运行模式各写一套,而是由 Electron IPC 和 Fastify 路由共同映射到同一层服务。
Bridge 与统一契约
渲染层通过统一的 site 接口访问后端。
- 在 Electron mode 下,这个接口背后是 preload 暴露出来的 IPC 调用
- 在 Web mode 下,这个接口背后是对
/api/*的fetch请求
这套统一契约让渲染层代码基本不需要关心当前到底跑在 IPC 还是 HTTP 上。
渲染层结构
渲染层是一个 Vue 3 单页应用,核心依赖包括:
- Vue Router:负责页面导航
- Pinia:负责状态管理
- Element Plus 与 UnoCSS:负责 UI 组织
主导航包含仪表盘、文章、分类、标签、媒体库和设置,而编辑器使用一套独立的全屏工作区布局。
以编辑器为中心的共享状态
HexoPress 的一个重要设计是:编辑器不会把所有有价值的状态都关在自己内部。正文内容、选区、标题结构和 Front Matter 会被提升到共享状态层,供其他面板协同使用。
因此这些能力才能在不强耦合的前提下成立:
- TOC 与正文标题同步
- AI 面板理解全文和选区
- 媒体插入理解当前文章上下文
Hexo 作为库,而不是 CLI
HexoPress 不是每次操作都 shell 一次 hexo 命令,而是把 Hexo 作为 Node.js 库直接嵌入运行时。
这带来的好处包括:
- 直接访问 Hexo 的内存数据模型
- 更快的查询和统计
- 通过同一套 Front Matter 解析逻辑保证读写一致性
结果就是更少的进程开销,以及更稳定的编辑体验。
构建与交付
项目针对两种运行模式采用不同的构建路径:
- Electron mode:Electron Forge + Vite
- Web mode:Vite 构建前端,配合 esbuild 打包 Fastify 服务端
虽然交付方式不同,但整体架构目标是一致的:一套渲染体验,一套服务模型,两种部署选择。