设计:确认 M5 大厅/子游戏双 Web 激活模型(用户约束)

用户明确:大厅 Web 常驻、子游戏 Web 进入创建/返回销毁(不保活);同时只一个激活(联网+收发包+界面更新),
非激活端 onInactive 彻底停网络+渲染;仅 大厅↔子游戏、无子游戏→子游戏;两 Web 各自独立桥+能力。

- 框架 §7.1:子游戏切换加"双 Web 激活模型"铁律块;M2/M4 单 WebView loadUrl 标为过渡实现
- 框架 §9:Web 保活/预热行改为双 Web 槽 + onActive/onInactive 模型
- 01_WBS:T-M5-01/02 重写为双 Web 槽(大厅常驻保活 + 子游戏临时 + 仅一个激活 + 各自独立桥),估时上调
- 记入项目记忆 m5-dual-web-activation-model
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lanterngamescn
2026-06-25 21:49:45 +08:00
parent 6bec98d584
commit d196b13e39
2 changed files with 12 additions and 4 deletions
+2 -2
View File
@@ -208,8 +208,8 @@
| ID | 目标 | 产出物 | 依赖 | 验收 | 估时 | 角色 | | ID | 目标 | 产出物 | 依赖 | 验收 | 估时 | 角色 |
|---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
| **T-M5-01** | Web 保活/预热 | `NodeController`+`BuilderNode` 离屏预创建/保活;启动期预热空 Web | T-M2-10 | 子游戏切换 <300ms、无白屏 | 2 | 桥 | | **T-M5-01** | Web 保活/预热(**双 Web 槽**模型,框架 §7.1/§9 确认)| 大厅 Web 常驻(`NodeController`/`BuilderNode` 离屏保活);子游戏 Web 进入创建/返回销毁;**同时只一个激活**:进子游戏大厅 `onInactive()` 停网络+渲染、返回 `onActive()` 恢复并销毁子游戏 Web;各 Web 独立桥+能力;无子游戏→子游戏 | T-M2-10 | 子游戏切换 <300ms、无白屏、返回保留大厅状态/连接、非激活端不占网络 | 3 | 桥 |
| **T-M5-02** | 切换与桥重绑 | 子游戏切换走 `loadUrl` 复用;切换后桥/handler 重绑时序正确 | T-M5-01 | 切换后桥功能正常 | 1 | 桥 | | **T-M5-02** | 切换与桥重绑 | 子游戏 Web 创建即注册自己的桥+能力;销毁时 dispose;大厅桥常驻不重绑。替换 M2/M4 的单 WebView loadUrl 切换 | T-M5-01 | 切换后两端桥功能各自正常、无泄漏 | 1.5 | 桥 |
| **T-M5-03** | 高频节流/批处理 | 定位/电量等高频 handler 节流;出站批处理 | T-M3-* | 跨引擎调用次数下降、无卡顿 | 1 | 桥 | | **T-M5-03** | 高频节流/批处理 | 定位/电量等高频 handler 节流;出站批处理 | T-M3-* | 跨引擎调用次数下降、无卡顿 | 1 | 桥 |
| **T-M5-04** | 崩溃兜底/内存 | `onRenderExited` 重载;`aboutToDisappear` 彻底清理 | T-M2-10 | 渲染子进程崩溃可自恢复 | 1 | 桥 | | **T-M5-04** | 崩溃兜底/内存 | `onRenderExited` 重载;`aboutToDisappear` 彻底清理 | T-M2-10 | 渲染子进程崩溃可自恢复 | 1 | 桥 |
| **T-M5-05** | 安全加固 | WebDebug 按 `isDebug` 守卫;密钥下沉服务端;明文 HTTP 域名白名单;file 跨域最小授权;自定义 scheme 注册(module.json5);日志脱敏 | 各能力就绪 | 安全审查清单(附录 B)全过 | 2 | 桥/台 | | **T-M5-05** | 安全加固 | WebDebug 按 `isDebug` 守卫;密钥下沉服务端;明文 HTTP 域名白名单;file 跨域最小授权;自定义 scheme 注册(module.json5);日志脱敏 | 各能力就绪 | 安全审查清单(附录 B)全过 | 2 | 桥/台 |
@@ -500,7 +500,15 @@ export struct BridgeGameContainer {
- **入口 URL**`weburl` 空 → `file://<解压根>/gamehall/index.html?Launchtype=0`;非空 → `http://<weburl 去-换/>?Launchtype=0`(《契约规范》§3/§5)。 - **入口 URL**`weburl` 空 → `file://<解压根>/gamehall/index.html?Launchtype=0`;非空 → `http://<weburl 去-换/>?Launchtype=0`(《契约规范》§3/§5)。
- **前后台**`UIAbility.onForeground/onBackground``callHandler('appservice','1'|'2')` - **前后台**`UIAbility.onForeground/onBackground``callHandler('appservice','1'|'2')`
- **子游戏切换**(路径 A`SwitchOverGameData`):同容器 `controller.loadUrl()` 到目标目录,桥与 handler 不变 - **子游戏切换**(路径 A`SwitchOverGameData`):M2/M4 先用同容器 `controller.loadUrl()` 到目标目录跑通;**M5 演进为双 Web 保活模型(见 §9)**
> **🔴 大厅/子游戏激活模型(M5 确认,2026-06-25**
> - **双 Web 槽****大厅 Web 常驻**;**子游戏 Web 进入时创建、返回大厅时销毁**(子游戏不保活)。
> - **同时只有一个激活**(激活=联网+收发包+界面更新):进子游戏 → 大厅 Web `onInactive()` **彻底停网络+渲染**;返回 → 销毁子游戏 Web、大厅 `onActive()` 恢复(返回快、保留大厅状态/连接)。
> - **切换拓扑**:仅 大厅↔子游戏,**无 子游戏→子游戏**(只需一个子游戏槽)。
> - **各自独立桥+能力**:大厅 Web 与子游戏 Web 各持一套 `BridgeController` + `buildCapabilities()` 注册;激活者响应。
> - 注:`onInactive()` 暂停 JS/渲染/多数活动;H5 自开的 WebSocket 在原生层未必完全断(H5 零改动下最接近的原生手段)。
> - M2/M4 的单 WebView `loadUrl` 切换是过渡实现,M5 用 `NodeController`/`BuilderNode` 离屏保活大厅 + 临时子游戏 Web 落地此模型。
### 7.2 GenericWebContainer(通用网页容器) ### 7.2 GenericWebContainer(通用网页容器)
@@ -609,7 +617,7 @@ INIT → LOAD_LOCAL_CONFIG → REQUEST_PERMISSIONS → FETCH_REMOTE_CONFIG
| 抓手 | 设计 | 收益 | | 抓手 | 设计 | 收益 |
|---|---|---| |---|---|---|
| **Web 保活 / 预热** | 用 `NodeController` + `BuilderNode` 离屏预创建并保活 Web 组件;大厅↔子游戏切换走 `loadUrl` 而非重建组件;可在启动期预热一个空 Web 实例 | 子游戏进入<300ms,避免内核重启白屏 | | **Web 保活 / 预热**(确认模型见 §7.1 | **双 Web 槽**:大厅 Web 常驻(`NodeController`/`BuilderNode` 离屏保活),子游戏 Web 进入创建/返回销毁;**同时只一个激活**——进子游戏时大厅 `onInactive()` 停网络+渲染,返回时大厅 `onActive()` 恢复并销毁子游戏 Web;各 Web 独立桥+能力;无子游戏→子游戏 | 子游戏进入<300ms、返回大厅秒回且保留状态/连接、非激活端不占网络/CPU |
| **并发卸载重活** | 下载/解压/解密/MD5 校验放 **TaskPool**(短任务)或 **Worker**(长驻);UI 线程零阻塞 | 启动期不卡顿,进度流畅 | | **并发卸载重活** | 下载/解压/解密/MD5 校验放 **TaskPool**(短任务)或 **Worker**(长驻);UI 线程零阻塞 | 启动期不卡顿,进度流畅 |
| **JSBridge 批处理** | 沿用 lzyzsd 队列语义:多条出站消息可在一次 `flushMessageQueue` 内聚合;高频 handler(定位/电量)做节流 | 减少 `runJavaScript` 跨引擎调用次数 | | **JSBridge 批处理** | 沿用 lzyzsd 队列语义:多条出站消息可在一次 `flushMessageQueue` 内聚合;高频 handler(定位/电量)做节流 | 减少 `runJavaScript` 跨引擎调用次数 |
| **资源就绪即渲染** | 本地 `file://` 优先;首屏资源预解压;`onPageEnd` 后再注桥,避免阻塞首屏;图片/音频懒加载 | 首帧更快 | | **资源就绪即渲染** | 本地 `file://` 优先;首屏资源预解压;`onPageEnd` 后再注桥,避免阻塞首屏;图片/音频懒加载 | 首帧更快 |