微前端中的 Orbz
Web Component 适合作为微前端边界,因为它的运行时契约由浏览器定义,而不依赖某一个框架。Orbz 可以由 Vue 远程模块渲染,由 Angular 宿主应用更新,之后再替换为 React 界面,而无需更改标签或属性。
Orbz 的定位是一个末端视觉组件,不承担路由系统或完整微前端平台的职责。导航、数据、身份与部署应继续使用现有的组合策略。将 orb-z 用作这些系统界面中共享的助手形象。
共享契约
最持久的集成方式是使用 Web 平台本身的标记:
<orb-z
state="idle"
size="18rem"
reduced-motion="system"
></orb-z>领域状态变化时,宿主应用或远程模块更新公开属性:
import type { OrbzElement, OrbzState } from "@neongate-ai/orbz";
export function renderAssistantState(state: OrbzState) {
const orb = document.querySelector<OrbzElement>("orb-z");
if (orb) orb.state = state;
}框架对象不会跨越这一边界。契约由字符串、数字、布尔属性和三个方法组成。
决定由谁注册元素
有三种实用模式。
1. 由宿主应用注册 Orbz
宿主应用只导入一次浏览器入口:
import "@neongate-ai/orbz/browser";远程模块仅渲染 <orb-z>。这样可减少重复的软件包代码,并明确由宿主应用管理版本。当宿主应用已经负责全局设计基础组件时,这是最清晰的默认方案。
2. 每个远程模块导入同一个固定版本
每个远程模块都可以独立依赖并导入 Orbz。注册是幂等的,因此后续导入会使用现有的 orb-z 定义,而不会重复定义。
各部署之间应协调使用软件包的同一个精确版本。Custom Elements 注册表无法替换已经定义的标签:页面上最先注册的版本生效。因此,即使注册本身没有抛出错误,版本不一致仍可能使行为取决于远程模块的加载顺序。
3. 通过打包器或 import map 共享 Orbz
Module Federation、import map 或其他运行时共享机制可以提供单个软件包实例。这可以减少重复字节,但属于优化,并非 Orbz 的要求。即使工具将软件包标记为单例,也要明确版本规则。
明确职责归属
为每项职责指定一个负责方:
| 职责 | 建议负责方 |
|---|---|
注册 orb-z | 宿主应用,或经过协调的共享依赖 |
| 语音会话与模型调用 | 助手功能或平台服务 |
| 将领域状态映射为 Orbz 状态 | 负责会话的功能模块 |
| 球体大小与预设 | 负责布局与品牌呈现的界面 |
| 状态文本与控件 | 渲染组件的远程模块 |
| Orbz 动画与内部样式 | Orbz 自身 |
避免多个远程模块写入同一个元素。共享服务可以发布助手的领域状态,但只有渲染球体的远程模块应负责映射并应用该状态。
传递领域状态,而非 DOM 指令
脆弱的契约会发布“将球体设为紫色”或“暂停第三层”之类的命令。这会将呈现细节泄漏到平台总线中。
更可靠的契约应发布有实际含义的应用状态:
type AssistantStatus =
| { phase: "ready" }
| { phase: "capturing" }
| { phase: "processing" }
| { phase: "playing" }
| { phase: "offline" }
| { phase: "error"; message: string };负责渲染的远程模块将 capturing 映射为 listening,将 processing 映射为 thinking,以此类推。错误仍应通过真实的文本与操作呈现,而不是变成没有文档说明的动画。
独立部署
代码仓库结构与部署结构是两个独立的选择。共享仓库可以方便本地编排,同时每个示例或微前端仍保持为独立的 Vercel 项目。反过来,互不相关的仓库也可以使用同一个 npm 版本,渲染完全相同的球体。
对于独立部署的界面:
- 将
@neongate-ai/orbz添加到该应用自己的依赖中; - 固定允许使用的版本,或集中管理该版本;
- 从应用客户端入口导入
/browser; - 通过应用现有的数据契约公开助手状态;
- 独立部署,无需导入 Orbz 源代码或其他示例应用。
Vanilla 、React 、Vue 、Svelte 、Angular 和 Next.js 在线示例展示了六个独立宿主如何使用同一套组件接口。
故障与回退行为
在注册之前,未知的自定义元素仍是有效但不具备行为的 HTML。这构成了有用的渐进增强边界:组件包加载时,周围的标签和控件仍可正常渲染。
设计宿主应用时,应确保没有动画也能理解助手的状态:
<div role="status" aria-live="polite">
<orb-z state="thinking"></orb-z>
<span>Assistant is preparing a response</span>
</div>如果远程模块加载失败,文本仍能传达状态。如果 Orbz 稍后才注册,元素将在原位置升级。
微前端检查清单
- 将 npm 软件包作为边界,不要从其他应用导入
src/。 - 为同时加载的远程模块协调使用同一个精确的 Orbz 版本。
- 可行时,在一个明确的位置完成注册。
- 每个已渲染的球体只由一个负责方写入。
- 在应用总线上发布领域状态,而非内部视觉细节。
- 将状态文本和控件保留在封闭的 Shadow DOM 之外。
- 在减少动态效果与 JavaScript 延迟加载的情况下测试宿主升级。
- 将标签名与文档记录的属性视为稳定的集成 API。