JavaScript 隔离
qiankun 支持多个微应用在同一页面中运行,并通过 JavaScript 隔离限制微应用对主应用全局对象的修改。该功能默认开启:每个应用使用独立的 window 视图,同时仍可访问常用的浏览器 API。
该机制用于减少可信应用之间的意外干扰,不能作为运行不可信代码的安全边界。
隔离模型
每个微应用都有一份虚拟全局对象,应用里的 window、self 和 globalThis 都指向这份视图。
| 操作 | 结果 |
|---|---|
写入 window.feature = value | 该值仅属于当前应用,不会写入主应用或其他微应用。 |
| 读取应用自己设置的全局变量 | 返回当前应用自己的值。 |
| 读取应用未设置的全局变量 | 沙箱会继续从主应用的全局对象中读取,因此标准浏览器 API 和主应用提供的全局对象仍然可用。 |
这种非对称行为是隔离机制的基础:写操作受隔离,读操作则尽可能与当前页面保持兼容。同一微应用的不同实例也各自拥有独立的全局视图。
qiankun 会隔离和追踪什么
应用定义的全局变量保存在虚拟对象中,不会修改主应用。除此之外,qiankun 还会追踪通过沙箱视图产生的部分常见副作用,包括:
- 尚未取消的定时器,以及注册在沙箱
window上的事件监听器; - History API 相关监听器;
- 动态插入的
<script>、<style>和<link rel="stylesheet">元素。
这些只是常见的可自动清理副作用,并不代表每一种浏览器 API 都会被拦截。
执行 unmount 时,qiankun 会清理已追踪的副作用,并停用当前应用的全局视图。应用自身的全局变量继续保持隔离,并可在后续重新挂载时复用;其他微应用无法访问这些变量。
微应用实例不再使用时,必须调用 unmount。如果跳过卸载,与该实例关联的清理逻辑也不会执行。
微应用仍需负责什么
沙箱不能替代应用自身的资源管理。qiankun 无法判断应用代码或第三方库创建的各类资源应在何时释放。
微应用仍应在 unmount 中主动释放自己的资源,尤其是:
- 框架根实例、路由实例、状态仓库和订阅;
- 应当停止的
WebSocket、EventSource、Worker 和进行中的请求; MutationObserver、ResizeObserver和IntersectionObserver;- 注册在应用容器之外的回调,以及插入容器之外的 DOM 节点。
显式清理可以保证应用在独立运行、重新挂载和多实例运行等场景下行为一致。
TIP
自动清理仅用于补充应用自身的清理逻辑,不能替代职责明确的 unmount 实现。
责任边界
- 它不是安全沙箱。 应用共享页面的 JavaScript 执行环境,并能读取未被自身覆盖的主应用全局变量,因此只能运行可信代码。
- 只有经过沙箱视图的操作才能被追踪。 通过沙箱之外的对象创建的资源仍由应用负责。
- 主应用仍能影响微应用。 对共享浏览器服务或主应用对象的直接修改,不会因为某个微应用卸载而回滚。
- 隔离不会创建私有后端或存储。 Cookie、Storage、网络服务等设施仍遵循浏览器原本的同源共享语义。
配置与下一步
sandbox 的默认值为 true。设置为 sandbox: false 后,微应用将直接共享真实全局对象,同时停用 qiankun 的原生 ESM 隔离机制。此配置仅适用于明确的兼容性需求,不应作为性能优化选项。传入对象而非 true 则在保持隔离的同时配置沙箱,见 SandboxConfiguration。
选项定义见 AppConfiguration,清理时机见微应用生命周期与 props,模块应用见原生 ESM 支持。维护者可以继续阅读 JavaScript 沙箱实现。
