HTML Entry 由主应用通过 fetch 拉取子应用 index.html,再用 DOMParser 解析,提取 scripts、styles 和 template;随后分别注入执行、挂载,并依赖框架(如 qiankun)实现 JS 沙箱与样式隔离,而非 HTML 本身提供隔离能力。

HTML Entry 是怎么被主应用加载并执行的
主应用不会直接 import 子应用的 JS 文件,而是用 fetch 拉取子应用的 index.html(即 HTML Entry),再用 DOMParser 解析它。关键不是“拿到 HTML”,而是从中提取三类东西:scripts(JS 资源 URL 或内联代码)、styles(CSS 链接或 style 标签内容)、template(body 内容)。这些内容后续会被分别注入、执行、挂载——整个过程绕开了直接执行子应用全局脚本的风险。
常见错误现象:
• 拉取到的 HTML 里 script 标签是相对路径(如 src="./main.js"),但主应用没设置 __webpack_public_path__ 或没重写 base href,导致 fetch 404
• 子应用 HTML 中有内联 script 直接调用 window.xxx = ...,未进入沙箱就污染了主 window
• 使用 document.write 或 eval 动态执行脚本,跳过沙箱控制逻辑
- 必须确保子应用所有静态资源路径(js/css/img)在 HTML Entry 中为绝对路径,或由主应用统一注入
__webpack_public_path__ - 不建议子应用在 HTML 中写内联脚本;如有,需确保其执行上下文已被沙箱接管(例如 qiankun 的
execScripts函数会把内联脚本包装进沙箱作用域) -
DOMParser解析后得到的doc.body.innerHTML才是最终挂载到容器中的 DOM 片段,不是原始 HTML 字符串
为什么 HTML Entry 天然支持样式隔离
HTML Entry 模式下,子应用卸载时,主应用会连同整个子应用 DOM 节点(含所有动态插入的 style、link)一并移除。浏览器收到 DOM 删除指令后,会自动触发 CSSOM 重建,原样式表立即失效——这比手动遍历、删 style 标签更可靠,也无需依赖 shadow DOM 或 CSS-in-JS 的运行时注入管控。
但以下情况仍会逃逸:
• 子应用在挂载后又通过 document.head.appendChild 插入新 style,该标签不在子应用根节点下,卸载时不会被清理
• 子应用使用 ant-design 等组件库,弹窗挂载到 document.body,其样式脱离容器,沙箱无法回收
• 子应用 HTML 中有全局作用的 style 标签(如 body { margin: 0 }),且未启用样式沙箱快照机制
立即学习“前端免费学习笔记(深入)”;
- 强制子应用所有 UI 渲染必须限定在容器节点内,对第三方组件库要显式传入
getContainer配置 - 禁用子应用直接操作
document.head;如需动态加样式,应走主应用提供的通信接口或 props 注入 - qiankun 默认开启样式沙箱(snapshot + style 标签增删),但仅对挂载期间注入的样式生效;HTML 中已存在的
style标签需靠快照对比还原
JS 沙箱不是靠 HTML Entry 实现的
HTML Entry 本身不提供 JS 隔离能力。它只是个“入口描述文件”,真正做 JS 沙箱的是框架层逻辑:比如 qiankun 在执行子应用脚本前,会用 Proxy 包裹 window,劫持 addEventListener、setTimeout、fetch 等 API,并在卸载时还原变更。但这仍是“运行时模拟”,无法阻止 eval('window.a = 1') 或 Function('return this')() 逃逸。
所以如果你看到“HTML Entry 实现了 JS 沙箱”,那是混淆了概念。真实可用的 JS 隔离只有:
• iframe(同域 about:blank)——引擎级隔离,唯一能防住所有逃逸手段的方案
• Web Worker(但无法操作 DOM)
• 无界(wujie)用 iframe + Web Component 组合,兼顾 DOM 可见性与 JS 隔离
- 别指望 HTML Entry 自带 JS 安全;沙箱必须由主应用在执行子应用脚本前主动创建
- Proxy 沙箱对 Vue/React 等框架兼容性较好,但对直接操作
window的老项目风险高,上线前必须跑eval、with、Function测试用例 - 若子应用含大量全局副作用(如改
console、监听beforeunload),建议优先用 iframe 方案,哪怕多一个 DOM 层级
子应用 HTML 中的 base 标签和 publicPath 怎么协同
<base href="/subapp/"> 和构建时配置的 __webpack_public_path__ 必须一致,否则子应用内部的 fetch('/api')、图片 src="./logo.png"、甚至 import('./chunk.js') 都会发错请求。HTML Entry 加载阶段,主应用需要在解析完 HTML 后,把子应用声明的 base 值提取出来,作为后续所有资源加载的基准路径。
常见错误现象:
• 子应用构建时设了 publicPath: '/subapp/',但 HTML 中没写 <base>,导致动态 import 加载 chunk 时拼成 /chunk.js 而非 /subapp/chunk.js
• 主应用用 fetch 拿到 HTML 后,直接 innerHTML = html,没处理 <base>,导致子应用内相对路径全部 404
• 多级嵌套路由(如 /app1/subpage)下,base 写死成 /app1/,但子应用实际部署在 /app1/subpage/,路径错位
- 主应用解析 HTML 后,必须读取
doc.querySelector('base')?.href,并以此为准设置后续所有资源请求的 base URL - 子应用构建时不要硬编码
publicPath,应通过环境变量或运行时注入(如__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__ || '/') - 如果子应用用 Vite,需配置
build.base并确保与主应用解析出的base一致;否则import.meta.env.BASE_URL会失效



















