09 · 常见问题
架构与职责
Q:Qiankun 和 single-spa 各自做什么?
- single-spa:应用注册、路由活跃规则、生命周期状态机、Parcel。
- Qiankun:HTML 入口流式加载、JS 沙箱、资源转译(Blob/依赖)、fetch 增强、与上述生命周期对象拼装。
Q:为什么拆成 loader / sandbox / shared?
边界清晰、可测、可复用;门面包 qiankun 只做编排(见 02-Monorepo包职责与数据流.md)。
加载与入口
Q:子应用入口为什么规定只能有一个带 entry 的 script?
loadEntry 需要唯一确定「何时算加载完成」以及 latestSetProp 对应哪次导出;多入口会破坏完成语义,直接抛 QiankunError。
Q:流式加载比一次性 innerHTML 好在哪?
更快见到 DOM;阻塞脚本/样式窗口内可 preload 后续资源;代价是 chunk 边界与 head 替换要实现稳健(参见 TagTransformStream FIXME)。
Q:<head> 为什么要改成 <qiankun-head>?
避免子应用 head 与宿主 document.head 混用;配合 sandbox 对 document.head 的 patch,把操作重定向到容器子树。
沙箱
Q:Qiankun 3 沙箱大致怎么实现?
- Membrane(Proxy):写副本、读合并、原生 API 重绑定防
Illegal invocation。 - Compartment:
with(this)+bind到唯一window.__compartment_globalThis__*。 - Patcher:动态插入、定时器、监听等在 unmount 时
free()。
Q:沙箱能 100% 防逃逸吗?
不能。例如 SystemJS 间接 eval 需要把 System 写回真实 window(源码 FIXME + 白名单)。应强调 威胁模型:防日常全局污染为主,不等价于安全沙箱。
Q:latestSetProp 是什么?
Membrane 记录伪全局上最后一次成功 set 的属性名,Loader 用它取入口 bundle 挂上去的导出对象。
脚本执行与调试
Q:为什么要 fetch 脚本再包一层 Blob 执行?
浏览器原生 script[src] 无法在 Qiankun 的 with(伪全局) 中执行;必须先取源码再用 makeEvaluateFactory 包装。
Q:为什么执行时要把 Blob URL 换回真实 URL?
让运行时代码里依赖「当前脚本 URL」的逻辑更接近生产;同时 revokeObjectURL 释放内存(见 script.ts 注释)。
依赖与样式
Q:如何实现与主应用共享 React/Vue 等依赖?
构建侧产出 script[type=dependencymap] JSON;运行时 moduleResolver 按包名 + semver range + peerDeps 顺序匹配主应用已声明依赖,命中则复用 URL(可能经 ObjectURL 映射)。
Q:Qiankun 默认解决 CSS 冲突吗?
默认仍是全局样式表;隔离需工程手段(前缀、CSS Modules、微应用规范)。源码里 dynamicAppend 对 styled-components 等有特殊处理,且有「挂到真实 document」类 FIXME,说明样式仍是难点。
生命周期与边界情况
Q:beforeLoad 一定在子应用 DOM 插入前执行吗?
不一定。loadApp 内 FIXME 指出:loadEntry 异步与 appendChild/内联脚本同步执行交织,beforeLoad 可能需要 transformer 协调。
Q:同一容器多次 loadMicroApp 会怎样?
通过 XPath 记忆 loadApp 结果,避免重复执行入口;mount 前会等待同容器上前序实例 unmount,避免并发问题。
Q:同屏两个同名子应用要注意什么?
genInstanceId 递增;removeWebpackChunkCacheWhenAppHaveMultiInstance 去掉 data-webpack,否则 webpack runtime 可能认为脚本已加载而跳过执行。
性能
Q:有哪些内置优化?
Fetch LRU(50)+ clone、重试、throw;流式阻塞窗口 preload;依赖复用;同步脚本 fetchPriority;v3 弃用手动 prefetchApps 而强调 loader 侧自动 preload。
与 Umi
Q:Umi 的 qiankun 插件和本仓库是什么关系?
Umi 解决工程化(构建、publicPath、生命周期导出模板等);Qiankun 解决运行时加载与隔离。排查问题时先分清是 构建配置 还是 运行时 行为。
开放话题(可结合 Issue)
- 子应用 保活/缓存(如 Issue #3057):框架保持agnostic,常由业务与具体 UI 框架方案承接。
- v3 文档与 demo 类任务(如 #2683、#2684):以仓库最新状态为准。
返回总目录:readme.md