跳到正文
开发者文档/模块系统

长文档建议按当前分组逐页阅读;右侧辅助栏会保留当前位置和快速操作。

开发者文档

模块系统

模块系统把应用内“更多”页面、网站模块构建产物、Tauri 本地 bundle 桥接、Capacitor 本地缓存和远程 open_url 兜底连接起来。它不是简单 iframe 列表,而是一条从模块中心到运行时宿主的完整发布与加载链路。

模块中心

`src/utils/module_center.js` 提供 DEFAULT_MODULE_CENTER、normalizeModuleCenterEntry 和 buildModuleCenterCards。内置模块优先保证入口稳定,远程 catalog 再补充 manifest_url、描述、排序和兼容信息。

  • 远程模块默认渠道是 main,也支持 dev 和 latest。
  • 配置 modules、远程 catalogModules 与内置 DEFAULT_MODULE_CENTER 会按 id 合并。
  • 内置游戏入口不依赖线上 catalog,避免远程目录滞后导致入口消失。

远程目录

`src/utils/more_modules.js` 使用 MODULE_CDN_BASE 指向模块 CDN。运行时缓存包含 hbu_more_module_state_v1、hbu_more_module_catalog_cache_v1、hbu_more_module_manifest_cache_v1 和 hbu_more_module_remote_source_rotation_v1。

  • catalog.json 是渠道入口;manifest.json 是单模块发布入口。
  • 远程候选地址会在当前 CDN、GitHub raw 和代理之间选择,但 iframe 打开时会避开常见代理。
  • 缓存只是可用性兜底,不能当作发布成功证明。

内置模块清单

合成湖工大

hecheng_hugongda

默认 order=1,远程模块,来自 DEFAULT_MODULE_CENTER 与网站模块产物。

跳出湖工大

jump_out_hbut

跳一跳风格小游戏,走 manifest_url 下载或远程打开链路。

2048 湖工大版

hbut_2048

内置入口不依赖线上 catalog,避免 catalog 滞后导致入口消失。

笨鸟先飞

clumsy_bird_hbut

飞行点击类小游戏,构建后进入 website/public/modules。

湖工大富翁

hbut_monopoly

校园投骰经营小游戏,模块包同样发布到 main、dev、latest。

湖工矿工

hbut_miner

抓取类小游戏,module.json 指向 source_dir=project。

湖工记忆牌

hbut_memory_match

翻牌配对模块,入口为 index.html。

湖工五子棋

hbut_gomoku

本地双人五子棋,是网站模块契约覆盖的新增游戏之一。

manifest 字段契约

catalog.json
渠道级远程目录,包含 schema_version、generated_at、channel、source_channel 和 modules 列表。
manifest.json
单模块发布清单,模块中心会通过 manifest_url 获取它。
package_url
主 bundle.zip 下载地址,桌面端准备本地包、移动端下载缓存都依赖它。
package_urls
候选下载地址列表,more_modules 会去重并按场景选择。
package_sha256
模块压缩包完整性校验值,Tauri 与 Capacitor 本地缓存都使用它判断是否需要刷新。
package_size
发布脚本记录的 bundle 大小,用于发布治理和排错。
entry_path
模块 HTML 入口,默认 index.html,不能包含 .. 这类越界路径。
open_url
远程直开兜底地址,Web 或移动端无法本地预览时使用。
min_compatible_version
最低兼容版本,MoreView.vue 会结合当前 App 版本做兼容判断。

运行时打开链路

  1. MoreView.vue 首先读取远程配置 module_center,再调用 buildModuleCenterCards 合并 DEFAULT_MODULE_CENTER、配置 modules 与 catalogModules。
  2. normalizeModuleCenterEntry 会把 id、name、kind、order、key_required、view、min_compatible_version 和 manifest_url 归一化。
  3. 用户点击远程模块后,MoreView.vue 拉取 manifest.json,检查版本兼容,再调用 prepareAndOpenModule。
  4. prepareAndOpenModule 在桌面端优先走 prepare_module_bundle;在 Capacitor 端走本地 Filesystem 下载解压;在 Web 端走 remote-site 远程预览。
  5. MoreModuleHostView.vue 接收会话后通过 normalizeModuleHostSessionPayload 和 resolveModuleHostPreviewSource 修正 preview_url、preview_mode、open_url 和本地缓存路径。

tauri-local

桌面端本地桥接模式,preview_url 指向 http://127.0.0.1:4399/module_bundle/content/...。

capacitor-local

移动端本地文件模式,Filesystem 写入 Directory.Data 后通过 toNativeFileSrc 转换本地 URL。

remote-site

远程站点模式,使用 open_url 或远程候选地址直接在宿主 iframe 中打开。

Tauri 本地 bundle 桥

  • src-tauri/src/modules/module_bundle.rs 使用 MODULE_CACHE_ROOT=more_modules,把模块按 channel/module_id/version 缓存在 AppCache 下。
  • ModuleBundlePrepareRequest 接收 channel、module_id、version、package_url、package_urls、package_sha256、entry_path 和 min_compatible_version。
  • prepare_module_bundle 会优先检查本地 metadata 与 package_sha256,命中时直接返回 ModuleBundlePrepareResult。
  • 未命中缓存时下载 bundle.zip,校验 sha256,解压 site 内容,写入 bundle.zip 和 metadata。
  • build_preview_url 生成本地预览地址,open_module_bundle_window 可打开独立模块窗口。
  • resolve_module_bundle_file 负责把本地桥接 URL 映射回缓存目录文件,并阻断越界路径;文档中把这类风险称为 zip slip 防护。

构建与发布链

  • scripts/build_website_modules.mjs 从 website/modules-src 扫描每个 module.json,跳过 disabled=true 的模块。
  • module.json 至少要声明 id、name、entry_path,可选 source_dir、dist_dir、order、icon、key_required、min_compatible_version 和 release_notes。
  • 脚本会在模块 source_dir 内执行 npm ci 或 npm install,再执行 npm run build,读取 dist_dir 作为静态站点产物。
  • PUBLISH_CHANNELS 固定为 main、dev、latest;每个渠道都会写入 website/public/modules/{channel}/{moduleId}。
  • 每个模块版本目录包含 site、bundle.zip、manifest.json;模块根目录也会写一份最新 manifest.json。
  • 发布 manifest 会记录 published_channel 和 source_channel,catalog.json 按 order 排序,供客户端模块中心拉取。

模块安全边界

  • 模块包可以渲染独立 HTML/JS,因此入口和远程来源必须来自受控 catalog 与 manifest。
  • package_sha256 是完整性检查,不等同于发布者身份认证;安全隐私页已说明它不是非对称签名。
  • entry_path 和 zip entry 都必须禁止绝对路径、`.`、`..`,防止 zip slip 或目录越界。
  • MoreModuleHostView.vue 只能消费归一化后的 preview_url,不能直接信任远程 payload。

模块维护清单

  1. 新增模块时先补 website/modules-src/{id}/module.json,再确认源码目录、构建脚本、dist_dir 和 entry_path 都存在。
  2. 发布前运行 scripts/build_website_modules.mjs 需要注意它是写入型脚本,会安装依赖、构建模块并覆盖 website/public/modules。
  3. 模块入口异常时先检查 catalog.json、manifest.json、package_url、package_sha256、bundle.zip 和 preview_url。
  4. 桌面本地桥异常时检查 canUseLocalModuleBridgePreview、prepare_module_bundle 返回值、bundle_path 和 /module_bundle/content 路由。
  5. 移动端本地包异常时检查 Capacitor、Filesystem、toNativeFileSrc、local_preview_url 与 preview_mode=capacitor-local。
  6. 调试桥可通过 debug_reset_more_modules 清理模块缓存,但只能在明确开启调试桥和本地 token 正确时使用。

验证入口

scripts/test_more_module_bridge.mjs

该脚本读取远程 catalog.json、manifest.json,调用 /module_bundle/prepare,确认返回的 preview_url 命中 /module_bundle/content,并抽取 HTML 与资源文本确认不是占位页。

website_game_modules_contract.spec.ts

该契约测试确认 website/modules-src 中的游戏与 DEFAULT_MODULE_CENTER 对齐,覆盖 hbut_gomoku、 hbut_2048 等模块入口,并检查宿主不会在移动端使用桌面本地桥 URL。

源码证据索引

  • 入口合并:src/utils/module_center.js 的 DEFAULT_MODULE_CENTER、normalizeModuleCenterEntry、buildModuleCenterCards。
  • 远程目录与缓存:src/utils/more_modules.js 的 MODULE_CDN_BASE、hbu_more_module_state_v1、hbu_more_module_catalog_cache_v1、hbu_more_module_manifest_cache_v1、hbu_more_module_remote_source_rotation_v1。
  • 用户入口:src/components/MoreView.vue 的 catalog 拉取、manifest 检查、isManifestVersionCompatible、prepareAndOpenModule 和导航 payload。
  • 宿主入口:src/components/MoreModuleHostView.vue 与 src/App.vue 的 more_module_host、moduleHostSession、preview_url 修复逻辑。
  • 桌面本地包:src-tauri/src/modules/module_bundle.rs 的 ModuleBundlePrepareRequest、ModuleBundlePrepareResult、prepare_module_bundle、open_module_bundle_window、resolve_module_bundle_file。
  • HTTP 桥:src-tauri/src/http_server.rs 的 /module_bundle/prepare、/module_bundle/open、/module_bundle/content、/debug/reset_more_modules。
  • 构建脚本:scripts/build_website_modules.mjs 与 website/modules-src/*/module.json。
  • 专项验证:scripts/test_more_module_bridge.mjs 与 src/utils/website_game_modules_contract.spec.ts。

继续阅读

推荐阅读路径

相关文档

当前页面读完后,可以按下面的交叉链接继续。用户文档、开发者文档、故障排查、参考资料和历史文档会互相补充。