改动说明-fix-subapp-loading.md 4.3 KB

改动说明:fix-subapp-loading(基座微应用挂载健壮性修复)

日期:2026-09-10 | 分支:fix-subapp-loading(基于 master b5a6721d)| 范围:仅 mky-vent-base 依据:docs/17 §8 实测("风量监测"新开标签页永久加载)、docs/16 基座审核 #6、docs/15。 原则:小步修改,不改业务逻辑与子应用通信协议;每处带 [fix-subapp-loading] 注释;可单项 revert。

背景一句话

用户典型路径(首页点"风量监测"→新开标签页)出现永久"正在加载":基座的两层加载遮罩(启动屏 + ventModal 挂载遮罩)的收起条件完全依赖"三维子应用就绪",而生产所部署的子应用构建存在绘制链停摆缺陷 → 遮罩永挂、整页不可用。本分支让基座在该场景下超时放行,并修复子应用卸载竞态。

改动明细(6 文件,2 组提交)

第 1 组:挂载遮罩超时兜底 + 就绪等待防中断

文件 改动
src/utils/domUtils.ts resetMicroContentWH(domId, callBack, maxWaitMs = 60000):新增 maxWaitMs 参数(默认 60s,向后兼容)。原实现每秒无限轮询等待 #容器 出现首个子节点——微应用挂载失败时容器永远为空,遮罩永久转圈。现超时后强制执行 callBack()(隐藏遮罩、放行页面)并停止轮询(原实现还有轮询本身永不停止的小泄漏)。超时时输出 console.error 便于定位。
src/components/vent/micro/ventModal.vue(3D 容器) onMountedmountMicroApp(...)tryresetMicroContentWH(...) 移入 finally——若 mount 同步抛错,就绪等待仍然启动,遮罩不会因"抛错跳过收起逻辑"而永久卡死。
ventModal2D.vue / needAir.vue / ventDoc.vue 同款 try/finally(分别对应 2D / 需风量 / 内业三个子应用容器)。

为什么是 60 秒:正常暖缓存挂载 ≤10s(实测 8.6~10.6s),冷缓存 40~60s;60s 仍未见容器内容基本可判定子应用挂载失败。超时放行后的表现:页面可见、三维区可能空白(用户可刷新重试),远好于无限转圈。参数可按现场调整(调大调小只改默认值)。

第 2 组:src/qiankun/index.ts 卸载竞态修复

unmountMicroApps 原实现两个 bug:

  1. multipleApp.filter(async (name) => { await …unmount() }) —— filter 的 async 回调使 await 不被任何方等待,卸载是"发射后不管";调用方 onBeforeUnmount(async () => { await unmountMicroApps(...) }) 以为在等,实际拿到的是 filter 的新数组(立即返回)。旧实例的卸载与新实例的挂载并发竞争容器。
  2. 判断条件 multipleApp.some函数引用(恒真),属笔误;且卸载后不清理 activeApps 注册表。

修复:改为 for…of Object.keys(activeApps) 顺序 await 卸载,try/catch 单个失败不阻断其余,卸载成功后 delete activeApps[key];入参空数组直接返回。匹配语义保持原样(name.includes(key))。

预期效果

场景 改前 改后
子应用挂载失败/停摆 整页"正在加载"永久转圈 最多 60s 后放行页面(附 console.error 定位信息)
门户在两个子应用宿主路由间切换 旧实例卸载与新挂载竞态,实例泄漏/争抢 卸载完成后再挂载,注册表干净
子应用正常挂载 正常 正常(无行为变化)

风险与回退

  • 本分支未改子应用通信协议、路由结构、任何业务页面;最坏情况是"超时放行后三维区空白"(与改前"永久转圈"相比是改善)。
  • 回退:git revert 对应 commit 即可,两组改动相互独立。
  • 未做构建验证:本机无该仓库 node_modules(pnpm 工程,依赖未安装)。改动均为小范围 TS/Vue 模板级修改,已逐行自查;请审核者本地 pnpm install && pnpm build 验证后再合并。

与 VentModelWeb 修复分支的关系

VentModelWeb 侧的修复分支 perf-load-v5(Gogs 同服务 msx/VentModelWeb)解决三维子应用自身的切页重建/泄漏/绘制停摆;本分支不替代它,二者建议都合——本分支是基座侧的防御性兜底:即使未来子应用再出挂载问题,门户也不会整页永久卡死。