模块化在微前端中需通过作用域封装、运行时沙箱和生命周期管控三层协同实现隔离:模块作用域天然隔离但需防隐式泄漏;js沙箱(如proxy)拦截全局访问,避免污染;卸载时须清理资源并解除引用;跨应用共享须契约化,禁用隐式耦合。

模块化在微前端中不是单纯靠 import/export 实现隔离,而是通过“作用域封装 + 运行时沙箱 + 生命周期管控”三层配合,让父应用和子应用的模块彼此不可见、互不干扰。
模块作用域天然隔离,但需避免隐式泄漏
现代打包工具(如 Webpack)默认将子应用打包为独立 bundle,每个 bundle 内部使用模块系统(ESM 或 CommonJS),变量、函数、类都限定在模块作用域内。这本身已形成第一层隔离。
- 子应用的 import 只能加载自身打包产物内的模块,无法直接 import 父应用或其他子应用的源码模块(除非显式暴露)
- 父应用不能直接 require 子应用的内部模块,因为子应用脚本是动态加载、独立执行的,不在同一模块图中
- ⚠️ 风险点:若子应用在顶层作用域写
var utils = {...}或function init() {...},非严格模式下会挂到window,破坏模块边界——必须用 IIFE 或 ESM 封装入口逻辑
沙箱拦截全局访问,切断模块逃逸路径
模块作用域只管“定义”,不管“运行时行为”。子应用仍可能通过 window.xxx、document.querySelector 或 setTimeout 间接污染全局。这时需要 JS 沙箱介入:
- Proxy 沙箱(如 qiankun 默认启用)会代理
window,把子应用对全局对象的所有读写重定向到沙箱私有副本,真实window不变 - 子应用内部的模块如果依赖
window.fetch或window.addEventListener,沙箱会劫持这些 API,确保副作用仅限于当前实例 - 父应用的模块(如公共工具库)若需被子应用使用,应通过 显式注入 方式提供(例如生命周期钩子中传入
shared对象),而非挂载到全局
生命周期约束模块生命周期,防止残留引用
模块隔离不仅是“加载时不冲突”,更是“卸载后不留痕”。子应用 unmount 时,其内部模块创建的资源必须彻底清理:
- 模块内定义的定时器(
setInterval)、事件监听器(addEventListener)、Observer 实例,必须在unmount钩子中清除 - 子应用模块若缓存了 DOM 节点或第三方库实例(如 Chart 实例),需主动销毁,否则可能持有对父应用节点的引用,导致内存泄漏
- 父应用不应保留子应用模块的任何强引用(如缓存其导出对象),应让 GC 正常回收——模块实例应随子应用卸载而自然失效
跨应用模块共享需契约化,拒绝隐式耦合
真正需要共享的模块(如登录态、国际化、埋点 SDK),不能靠“大家都 import 同一个 npm 包”来实现,因为版本、实例、上下文可能不一致:
- 推荐由父应用统一提供 标准化接口(如
getAuthState()、translate(key)),子应用只调用,不自行初始化 - 若必须复用代码逻辑,可通过 Module Federation 共享编译后的模块,但需约定好 版本锁定 和 运行时上下文绑定(如所有共享模块接收
context参数,避免依赖全局) - 禁止子应用直接
import父应用源码路径(如import { api } from 'main-app/utils'),这会引入构建耦合,破坏独立部署能力
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











