HTML Entry模式下子应用按需加载需用DOMParser解析HTML字符串,重写script/src、style/link路径,内联脚本交沙箱执行,动态样式需快照隔离,禁用document.head直接注入。

HTML Entry 模式下子应用怎么真正“按需加载”
不是把 HTML 字符串 fetch 过来就完事了——关键在“解析后分发”,否则 script 404、样式漏载、内联脚本逃逸全是常态。
- 必须用
DOMParser解析返回的 HTML 字符串,不能直接innerHTML = htmlStr;否则<script src="./main.js"></script>中的相对路径会以主应用 URL 为基准解析,大概率 404 - 提取出的
scripts列表要区分内联与外链:外链需补全为绝对 URL(靠new URL(scriptSrc, response.url)),内联脚本必须交由沙箱执行(如 qiankun 的execScripts),否则直接污染window -
styles同样要重写<link href>和<style></style>内容,避免 CSS 中的url(./icon.png)路径失效;建议子应用构建时设publicPath或主应用注入__webpack_public_path__
为什么 HTML Entry 天然支持样式卸载但需要“快照”补位
卸载时删掉整个子应用 DOM 节点,浏览器自动重建 CSSOM,样式确实清除了——但这只对初始加载的 <link> 和 <style></style> 有效。动态插入的样式仍会残留。
- 子应用运行时通过
document.head.appendChild(<style>)</style>加的样式,不在容器节点下,卸载不清理 → 必须禁用该操作,改用主应用提供的样式注入接口 - 第三方组件库(如 Ant Design)弹窗挂到
document.body,其样式脱离容器 → 需显式配置getContainer: () => container,强制渲染到子应用根节点内 - 全局作用样式(如
body { margin: 0 })会逃逸 → 开启 qiankun 的styleIsolation: 'scoped'或手动做样式快照(document.styleSheets列表在挂载前保存,卸载后恢复)
Shadow DOM + adoptedStyleSheets 怎么绕过 innerHTML 注入陷阱
直接 shadowRoot.innerHTML = htmlString 等于主动放弃隔离——内联 <style></style> 会逃逸到 light DOM,<script></script> 在全局执行,XSS 风险拉满。
- 必须用
DOMParser解析 HTML 字符串,再遍历所有<style></style>标签,提取textContent,用CSSStyleSheetAPI 创建实例:const sheet = new CSSStyleSheet(); sheet.replaceSync(styleText); - 注入时只能走
shadowRoot.adoptedStyleSheets = [sheet],不能 append 到shadowRoot—— 后者只是普通 DOM 插入,无作用域约束 -
<link rel="stylesheet">必须拦截并转成 CSS 字符串再注入;@import和相对url()需主应用代理重写,否则加载失败或路径错乱
iframe 方案里哪些 HTML 结构问题会导致“看不见却已加载”
iframe 白屏不报错,90% 是 HTML 结构或加载时机问题,不是 JS 错误。
立即学习“前端免费学习笔记(深入)”;
-
src值为空、javascript:void(0)或file://协议,现代浏览器静默拒绝 → 动态赋值前必须校验:if (url && (url.startsWith('http') || url.startsWith('/'))) - 未设宽高,或父容器是
display: flex/grid→ iframe 默认尺寸 300×150px,会被压缩至 0 → 必须显式写style="width: 100%; height: 400px;" - 子应用 HTML 中含
<base href="/sub/>%20%E4%BD%86%E4%B8%BB%E5%BA%94%E7%94%A8%E6%B2%A1%E5%90%8C%E6%AD%A5%E5%A4%84%E7%90%86%20%E2%86%92%20%E6%89%80%E6%9C%89%E7%9B%B8%E5%AF%B9%E8%B7%AF%E5%BE%84%EF%BC%88src%E3%80%81href%E3%80%81fetch%EF%BC%89%E9%83%BD%E9%94%99%E4%B9%B1%20%E2%86%92%20%E5%BC%80%E5%8F%91%E6%9C%9F%E7%94%A8%20http-server%20%E5%90%AF%E6%9C%8D%E5%8A%A1%EF%BC%8C%E7%94%9F%E4%BA%A7%E7%94%A8%E7%BB%9D%E5%AF%B9%E8%B7%AF%E5%BE%84 %0A
<script>%E3%80%81<style>%E3%80%81<img>%20%E9%83%BD%E6%8C%89%E9%A2%84%E6%9C%9F%E4%B8%8A%E4%B8%8B%E6%96%87%E6%89%A7%E8%A1%8C%E5%92%8C%E4%BD%9C%E7%94%A8%E2%80%94%E2%80%94%E8%B7%AF%E5%BE%84%E9%87%8D%E5%86%99%E3%80%81%E6%B2%99%E7%AE%B1%E7%BB%91%E5%AE%9A%E3%80%81%E6%A0%B7%E5%BC%8F%E6%B3%A8%E5%85%A5%E6%97%B6%E6%9C%BA%E3%80%81%E5%8A%A8%E6%80%81%E8%B5%84%E6%BA%90%E6%8B%A6%E6%88%AA%EF%BC%8C%E7%BC%BA%E4%B8%80%E4%B8%8D%E5%8F%AF%E3%80%82">



















