customelements.define() 不能直接用于微前端,因其仅注册标签与类映射,缺乏挂载上下文、沙箱隔离和资源卸载能力;重复注册会报“already been used”错误,需加守卫判断是否已定义;shadow dom 必须在 constructor 中用 attachshadow({ mode: 'closed' }) 初始化以保障隔离;子应用生命周期必须桥接 connectedcallback 和 disconnectedcallback 实现加载与卸载;attributechangedcallback 是唯一安全通信通道,需声明 observedattributes 并手动解析属性值。

customElements.define() 不能直接当微前端用,它只是注册一个标签名和类的映射关系,不带挂载上下文、沙箱作用域、资源卸载能力——拿它直接塞子应用,等于裸奔上线。
为什么 customElements.define() 会报 “already been used” 错误
这是开发期最常撞上的第一堵墙:同一个名字重复调用 customElements.define()。浏览器不允许二次注册,哪怕你 reload 页面或热更新时重新执行了定义逻辑。
- 必须加守卫:每次 define 前先查
customElements.get('my-app'),返回undefined才执行注册 - 不要在模块顶层无条件调用
customElements.define();把它包进函数里,由宿主按需触发 - Webpack/Vite 的 HMR 场景下,模块重载会导致类被重复定义,此时即使加守卫也不够——得配合
if (window.customElements.get('my-app') === undefined)+ 类名去重(比如加时间戳后缀)
attachShadow({ mode: 'closed' }) 必须写在 constructor() 里
没这行代码,所有样式隔离、DOM 封装、事件边界都不存在。Shadow DOM 不是可选项,是沙箱底线。
-
mode: 'closed'是生产唯一推荐模式:mode: 'open'允许任意脚本通过el.shadowRoot拿到内部节点,破坏隔离前提 - 必须在
constructor()中调用,不能拖到connectedCallback()—— 否则元素插入 DOM 时已暴露在 light DOM,样式早已穿透、事件早已泄漏 -
closed模式下el.shadowRoot返回null,但 DevTools 可展开#shadow-root查看结构,不影响调试
子应用加载和卸载必须桥接到生命周期钩子
connectedCallback() 和 disconnectedCallback() 是你唯一能控制子应用启停的入口,不手动桥接,就等于没卸载。
- 在
connectedCallback()中动态import('./app-react.js'),并缓存模块导出的mount()函数;避免全局<script></script>标签导致多次执行 - 用
WeakMap或实例属性保存子应用 root 实例(如 React 的createRoot),确保disconnectedCallback()能调用root.unmount() - 加载前检查
window.__MICRO_APP_LOADED__或类似标记,防止并发加载同一子应用引发状态混乱 - 不要依赖子应用自己监听路由变化来卸载——父应用切换路由时,
disconnectedCallback()才是唯一可靠信号
attributeChangedCallback() 是唯一安全通信通道
父应用传参不能靠 config='{"theme":"dark"}' 这种写法,因为所有 attribute 都是字符串,子应用拿到的是原始字符串,不是解析后的对象。
- 只监听明确声明的
static get observedAttributes() { return ['config', 'env']; },漏写就收不到变更 - 在回调里对
config做JSON.parse(newVal),注意捕获语法错误;布尔属性(如disabled)值可能是null或'true',不能直接=== true - 初始 HTML 中写的
<micro-app config='{"theme":"dark"}'></micro-app>会触发一次回调,oldValue是null,别拿它做相等判断
connectedCallback/disconnectedCallback 这两个钩子里——漏掉任意一环,内存泄漏、样式污染、重复加载就立刻出现。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











