微前端主应用需通过 createelement('html') 解析子应用 html 并注入沙箱,重写 script src 为绝对路径,声明 base href,设置 script type,移除内联事件与 defer/async,动态加载脚本,配置 publicpath,样式加前缀隔离,代理开发请求并设响应头。

微前端主应用如何加载子应用 HTML 入口
主应用不能直接用 fetch 拿 HTML 字符串再 innerHTML 插入——这会导致 script 不执行、样式隔离失效、资源路径错乱。必须让浏览器原生解析 HTML,同时控制其执行上下文。
主流方案是用 iframe 或动态创建 script + link 标签并手动触发,但前者隔离过强(通信/样式共享难),后者漏加载或执行顺序不可控。推荐做法:用 document.createElement('html') 解析后提取 head 和 body 内容,再注入沙箱容器,并重写 script 的 src 为绝对路径(避免相对路径 404)。
- 子应用 HTML 必须声明
<base href="/subapp/">,否则图片、字体等静态资源会从主应用路径加载 - 所有
<script></script>标签需设type="application/javascript",否则某些微前端框架(如 qiankun)无法识别并接管执行 - 禁止在子应用 HTML 中写内联
onclick或onload,这些事件绑定不会被沙箱捕获,会逃逸到主应用作用域
子应用 HTML 中的 script 加载时机与执行控制
子应用的 <script src="entry.js"></script> 在 HTML 解析阶段就会被浏览器预加载,但微前端要求它延迟到 mount 阶段才执行——否则会污染全局、抢跑初始化逻辑。
解决方法不是删掉 script 标签,而是把它转为“惰性 script”:把 src 提取出来,挂载时用 document.createElement('script') 动态创建并插入,同时设置 crossorigin="anonymous"(避免因跨域导致 error 事件无法捕获)。
- 若子应用用了
defer或async,必须移除——它们会让脚本脱离微前端生命周期控制 - Webpack 打包时需配置
output.publicPath: 'auto'或明确写死为子应用域名,否则__webpack_public_path__仍指向主应用地址 - Vue/React 子应用若用了
runtime-only构建,HTML 中的render函数调用必须包裹在window.__POWERED_BY_QIANKUN__判断里,否则独立访问时白屏
HTML 入口中的样式隔离与冲突预防
直接插入子应用 <style></style> 标签会导致全局污染,尤其当多个子应用用相同 class 名(如 .btn)时。CSS in JS 或 CSS Modules 只解决组件层,HTML 入口里的全局样式仍需处理。
最轻量做法:给子应用根节点加唯一前缀类名(如 subapp-user-center),再用 PostCSS 插件 postcss-prefix-selector 批量重写其 HTML 中所有 <style></style> 规则的选择器。不依赖框架运行时,构建时就完成。
- 不要用
<style scoped></style>—— 它只作用于单文件组件,对 HTML 入口里的<style></style>无效 - 如果子应用用了第三方 UI 库(如 Ant Design),其 CSS 是通过
link引入的,需在主应用中拦截该请求,改写响应内容,为每条规则添加前缀(可借助qiankun的getPublicPath+ 自定义 fetch hook) -
<style></style>标签里含@import时,PostCSS 默认不处理,需额外启用postcss-import插件
本地开发时 HTML 入口的代理与热更新适配
本地启动主应用时,子应用 HTML 通常由另一个 dev server 提供(如 http://localhost:8081),但浏览器同源策略会阻止直接 fetch。不能简单配 webpack devServer proxy,因为 HTML 响应头需带 Content-Type: text/html,而 proxy 默认可能丢失或篡改。
正确做法是在主应用 devServer 的 setupMiddlewares 钩子中,用 axios 代理请求,并显式设置响应头:
app.get('/subapp/index.html', async (req, res) => {
const html = await axios.get('http://localhost:8081/index.html');
res.set('Content-Type', 'text/html; charset=utf-8');
res.send(html.data);
});
- 子应用 devServer 必须开启
headers: { 'Access-Control-Allow-Origin': '*' },否则 fetch 会失败 - 如果子应用用了 HMR,其
hot-update.json请求路径仍基于子应用自身端口,主应用代理时需同步重写所有/js/、/css/路径为http://localhost:8081/xxx - 本地调试时,建议在子应用 HTML 中加
<!-- DEBUG: powered by qiankun -->注释,避免误部署到生产环境
HTML 入口改造看着只是改几行标签,实际牵扯路径解析、脚本执行时序、样式作用域、开发链路连通性四个层面。漏掉任意一环,都会表现为子应用白屏、样式错乱、按钮点击无反应——而且错误堆栈里几乎找不到线索。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











