es modules加载子应用需配合沙箱隔离与css隔离,否则必然污染全局:动态import()仅解决加载,proxy/快照沙箱约束js执行,shadow dom或css前缀防止样式泄漏,共享依赖须主应用统一注入。

在微前端中用 ES Modules 加载模块,关键不是“能不能加载”,而是“加载后怎么不干扰主应用和其他子应用”。ESM 本身不提供隔离能力,必须配合运行时机制来约束执行环境。
用动态 import() 加载子应用入口
这是最直接的方式。主应用根据路由或用户操作,按需加载子应用的 ESM 入口文件:
- 确保子应用构建为 ES Module 格式(Webpack 设置
output.libraryTarget = 'module',Vite 默认支持) - 使用
import('./http://subapp.example.com/entry.js'),注意必须是 绝对 URL,避免跨基路径解析错误 - 返回 Promise,解构出生命周期钩子:
bootstrap、mount、unmount - 浏览器需支持 CORS,子应用服务要配置
Access-Control-Allow-Origin,否则请求被拦截
加载后必须套沙箱,否则全局污染不可避免
ESM 模块执行时仍会直接访问 window、修改 history、挂载全局变量。仅靠 import() 无法阻止这类行为:
-
Proxy 沙箱:用
new Proxy(window, handler)拦截读写,子应用所有全局操作都落在代理层,卸载时丢弃代理对象(qiankun 默认方案) -
快照沙箱:在
mount前保存window快照,unmount后逐项还原被修改的属性(适合单实例、低频切换场景) - 不要依赖
iframe做 JS 隔离——它虽天然隔离,但通信成本高、样式穿透难、SEO 不友好,仅作为兜底或特殊场景选项
共享依赖要显式声明,避免重复加载
多个子应用都用 React 或 Vue,不能各自打包一份。需统一由主应用提供,并通过模块联邦或 SystemJS 映射暴露:
- 主应用用
import('react')提前加载,再通过define注入到子应用作用域(如 qiankun 的getPublicPath+globalThis注入) - 或用 SystemJS 配置
map,把'react'映射到主应用已加载的版本,子应用import 'react'时直接复用 - 避免子应用
import相对路径的 shared 包(如../shared/utils),这会绕过主应用控制,破坏隔离边界
CSS 隔离需同步处理,否则样式仍会泄漏
JS 模块加载和执行隔离了,CSS 还在全局生效。常见做法有:
- 子应用启用 CSS Modules 或 scoped style(Vue/Svelte),让类名哈希化
- 主应用用 Shadow DOM 包裹子应用容器,天然样式封闭(兼容性较好,Chrome/Firefox/Edge 稳定支持)
- 手动加前缀或用 postcss-prefix-selector 重写子应用 CSS 选择器,绑定到唯一容器 ID 下
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











