WU / 文档通用微前端
中文

DOM、CSS 与 sandbox

区分 DOM 所有权、样式隔离和 JavaScript realm,并理解它们与安全边界的区别。

三个独立决策

应用的行为取决于 JavaScript 在哪里执行、谁拥有 DOM 边界以及接收哪些样式。配置其中一个维度不会自动配置其他维度。

JavaScript 模式 执行方式 用途与限制
module 主窗口中的 import() 可信的现代模块;不隔离宿主全局变量
strict 在隐藏 iframe 内执行真实 import 独立 realm 与清理;要求模块可在其中加载
eval iframe 内的传统 HTML/scripts 路径 兼容 UMD/IIFE;不像 strict 那样支持 ESM 模块

eval 模式通过 HTML 兼容路径在 iframe 内执行脚本;ESM 模块应根据所需 realm 使用 module 或 strict。

Strict 及其回退

await wu.init({
  sandbox: 'strict',
  strictFallback: false,
  apps: [{ name: 'reports', url: '/apps/reports' }],
});

await wu.mount('reports', '#reports-slot');
console.table(wu.getSandboxInfo('reports'));

iframe 内 import 失败默认产生错误。strictFallback: true 明确允许降级到 eval 模式;它不会修复与该模式不兼容的 ESM bundle。应用级选项优先于全局选项。

getSandboxInfo 暴露 requestedMode、actualMode、isolationLevel、mounted、nativeShadow 和 domOwnership。诊断回退时比较 requestedMode 与 actualMode:配置表达期望,状态描述应用实际执行的模式。

谁拥有 DOM

domOwnership 结果
wu WU 创建外层 ShadowRoot,并向 renderer 提供内部根节点
app renderer 管理自身边界,适用于 LitElement
light 挂载时不使用 WU 外层 ShadowRoot

显式值优先。未设置时,nativeShadow: true 选择 app,false 选择 wu;两者都没有时,framework: 'lit' 选择 app,其余选择 wu。

名称 app 表达一种责任,不保证组件真的创建 Shadow DOM。如果 renderer 没有创建自身边界,内容仍处于它收到的 DOM 树中。

样式分发

配置应用 manifest:

{
  "name": "reports",
  "entry": "assets/reports.js",
  "styleMode": "own-only"
}
值 含义
shared bridge 允许将外部样式分发到 ShadowRoot
isolated / none 不注入额外外部样式
fully-isolated / own-only 注入被识别为属于该应用的样式

bridge 观察变化,并将样式归属到应用。宿主代码创建的样式表可以通过 wu.tagStyleAsApp(element, appName) 标记。不要假定 shell 的全局 CSS 规则能够穿越 ShadowRoot。继承的 custom properties 和可继承 CSS 属性仍可能影响内容外观。

sandbox 从 manifest 接收 styleMode。应在那里决定样式策略;宿主顶层配置中的同名字段不会在挂载时替代该值。

实际的信任边界

iframe 实现本身注明它与宿主同源,并将节点创建重定向到宿主文档。节点可能暴露 ownerDocument.defaultView,脚本可由此访问宿主。隐藏 parent 或 top 无法封闭此路径。

这些模式用于协调可信代码、全局变量和清理。执行不可信代码需要其他边界,例如隔离的源与受限协议;运行时的同源 iframe 仍保留潜在的宿主访问能力。

容器与布局

slot 应是 renderer 独占的区域。在 React/Vue 中,将 loading 信息放在挂载节点旁边:如果 shell 在同一节点内部协调其子节点,可能删除 WU 插入的树。仓库中专门的 Vue 测试重现了这种无报错故障。

宿主配置中的 fullBleed 决定微前端是否占满 slot 高度并负责自身滚动。如果内容应随文档自然流动,保留默认行为。slot 高度和布局仍由 shell 负责。

实现参考

模式:src/core/wu-core.js、src/core/wu-core.js、src/core/wu-core.js、src/core/wu-core.js;所有权:src/core/wu-sandbox.js;同源限制:src/core/wu-iframe-sandbox.js。测试:tests/unit/sandbox-honesty.test.js、tests/unit/native-shadow-sandbox.test.js、tests/unit/sandbox-container-ownership.test.js、tests/unit/style-own-only.test.js、tests/unit/style-cross-app.test.js、tests/unit/vue-slot-mount-target.test.js。

在 strict 中,parent.postMessage 遵守 targetOrigin,并将 sandbox 窗口作为 event.source。内部访问 __wuHostPostMessage 已移除。该身份修复不意味着同源 iframe 能隔离恶意代码。

一起完善 WU

发现了问题?有新的想法?

你的使用体验能让 WU 变得更好。告诉我们遇到的问题,或支持项目的持续开发。