Bridge 介绍
什么是 Bridge?
Bridge
是 Module Federation 提供的跨框架应用级模块加载与集成解决方案。它不仅仅是一个组件加载器,而是专门设计用于处理"应用级别模块"的完整生命周期管理系统。
Bridge 解决的核心问题是:如何让使用不同前端框架开发的完整应用能够作为模块被其他应用动态加载、渲染和集成,同时保持各自的技术栈独立性和业务完整性。与传统的组件级别共享不同,Bridge 处理的是包含路由系统、业务逻辑的完整应用模块。
通过 Bridge,您可以:
- 跨框架集成:在 React 应用中加载 Vue 应用,在 Vue 应用中加载 React 应用,实现真正的技术栈无关集成
- 应用级模块化:将完整的应用(包含路由、业务逻辑)作为模块进行导出和消费
- 组件级懒加载:支持细粒度的组件级加载,实现按需加载和性能优化
- 路由系统协同:支持复杂的嵌套路由场景,确保宿主应用与远程应用的路由能够无缝协作
- 生命周期管理:自动处理远程应用的挂载、卸载和更新,确保资源的正确管理
- 应用隔离:确保不同应用间的样式、脚本和上下文相互隔离,避免冲突
- 渐进式迁移:支持将单体应用逐步拆分为微前端架构,降低迁移风险
这些能力使 Bridge 成为构建现代化、可扩展微前端架构的核心基础设施。
支持的框架
React Bridge (@module-federation/bridge-react
)
专为 React 应用设计的 Bridge 工具包,支持 React 16-19 的所有版本,并兼容主流的 React 生态系统工具。
核心特性
- 版本兼容性:支持 React 16.x 到 19.x 的所有版本,自动处理不同版本间的兼容性问题
- 路由集成:深度集成 React Router,支持 v5、v6、v7 版本,自动处理 basename 和嵌套路由
- 框架隔离:确保不同应用间的 React 上下文和组件树相互隔离
- 性能优化:内置懒加载、代码分割和资源预加载机制
核心 API
createBridgeComponent
- 用途:将 React 应用包装为可远程加载的模块
- 适用场景:当您希望将 React 应用作为模块导出给其他应用使用时
- 特性:自动处理应用的生命周期、路由配置和错误边界
createRemoteAppComponent
- 用途:在宿主应用中加载和渲染远程 React 应用
- 特性:自动创建渲染上下文,处理路由集成和生命周期管理
- 优势:支持错误恢复、加载状态管理和性能监控
createLazyComponent
- 用途:组件级的懒加载,需要配合运行时插件使用
- 优势:更细粒度的加载控制和性能优化
- 场景:适用于大型组件库或复杂业务组件的按需加载
实践示例
Vue Bridge (@module-federation/bridge-vue3
)
专为 Vue 3 应用设计的 Bridge 工具包,充分利用 Vue 3 的现代化特性。
核心特性
- Vue 3 深度集成:完整支持 Composition API、响应式系统和 Teleport 等新特性
- 路由系统:与 Vue Router 4 深度集成,支持动态路由和嵌套路由
- 应用隔离:确保不同应用间的 Vue 实例和响应式系统相互隔离
- TypeScript 支持:提供完整的 TypeScript 类型定义和推导
- 开发体验:支持 Vue DevTools 和热模块替换
核心 API
createBridgeComponent
- 用途:将 Vue 3 应用包装为可远程加载的模块
- 支持:完整的 Vue 3 生态系统集成,包括插件系统和自定义指令
- 特性:自动处理应用实例的创建、挂载和销毁
createRemoteAppComponent
- 用途:在 Vue 应用中加载其他框架的应用模块
- 特性:自动处理 Vue 3 的组合式 API 和应用实例管理
- 优势:支持跨框架的DOM渲染和事件处理
常见问题
为什么需要 Bridge?
Bridge 解决了现代前端开发中的几个关键挑战:
-
技术栈多样性管理
- 大型组织中不同团队往往使用不同的前端框架
- Bridge 让这些团队能够独立开发,同时保持应用间的互操作性
- 避免了强制统一技术栈带来的迁移成本和开发效率问题
-
应用级模块化
- 传统的模块联邦主要处理组件级别的共享
- Bridge 支持应用级别的模块化,包含完整的业务逻辑和用户体验
- 实现了更粗粒度但更易管理的微前端架构
-
路由系统协同
- 支持加载带有复杂路由的应用模块
- 确保宿主应用和远程应用的路由能够协调工作
- 支持嵌套路由、动态路由和路由守卫等高级特性
-
渐进式架构演进
- 支持将现有单体应用逐步拆分为微前端架构
- 降低大规模重构的风险和成本
- 提供平滑的迁移路径
Bridge vs 传统组件共享
特性 | 传统组件共享 | Bridge 应用共享 |
---|
粒度 | 组件级别 | 应用级别 |
路由 | 不支持 | 完整支持 |
应用隔离 | 有限支持 | 完整隔离 |
业务完整性 | 片段化 | 完整业务单元 |
开发独立性 | 中等 | 高度独立 |
部署策略 | 依赖宿主 | 独立部署 |
组件级加载详解
除了应用级别的模块化,Bridge 还支持组件级别的懒加载,通过 createLazyComponent
API 提供更细粒度的加载控制。
使用场景
1. 大型组件库
- 按需加载复杂的业务组件,减少初始包大小
- 支持组件级别的版本管理和独立更新
- 适用于设计系统和共享组件库的场景
2. 条件性功能模块
- 根据用户权限或业务场景动态加载功能模块
- 支持 A/B 测试和功能开关
- 降低核心应用的复杂度
3. 性能优化
- 延迟加载非关键路径的组件
- 支持预加载和智能缓存策略
- 配合 Intersection Observer 实现可视区域加载
核心特性
- 数据预取:支持组件级别的数据预取,确保组件加载时数据已就绪
- 错误边界:内置错误处理机制,组件加载失败不影响主应用
- 加载状态:提供丰富的加载状态管理,支持自定义加载指示器
- 缓存机制:智能缓存已加载的组件,避免重复网络请求
- 类型安全:完整的 TypeScript 支持,确保组件接口的类型安全
与应用级加载的配合
组件级加载和应用级加载可以完美配合使用:
// 应用级加载 - 加载完整的远程应用
const RemoteApp = createRemoteAppComponent({
loader: () => import('remote/app'),
fallback: <AppSkeleton />
});
// 组件级加载 - 在远程应用内部按需加载组件
const LazyComponent = createLazyComponent({
loader: () => import('remote/heavy-component'),
loading: <ComponentSkeleton />,
fallback: ({ error }) => <ErrorBoundary error={error} />
});
这种分层的加载策略让您可以:
- 在粗粒度上实现应用间的解耦和独立部署
- 在细粒度上优化性能和用户体验
- 根据业务需要灵活选择合适的加载粒度
性能考虑
加载性能
- Bridge 支持应用级别的懒加载和预加载
- 内置资源缓存和版本管理机制
- 支持渐进式加载策略
运行时性能
- 框架隔离确保不同应用间不会相互影响
- 支持应用级别的性能监控和优化
- 内存管理和资源清理自动化
网络优化
- 支持资源共享和去重
- 内置 CDN 友好的资源加载策略
- 支持离线缓存和服务端渲染
如何扩展到其他框架?
目前官方提供了 React 和 Vue 3 的 Bridge 实现。如果您需要其他框架的支持:
- 提交需求:通过 GitHub Issues 告诉我们您的需求
- 参考实现:查看现有的 Bridge 实现 来了解如何开发
- 贡献代码:欢迎为社区贡献新的框架支持
Bridge 的实现原理
Bridge 的核心思想很简单:基于 DOM 的渲染抽象。以下是简化的实现原理:
导出端(远程应用)
export default function createProvider() {
const rootMap = new Map<HTMLElement, ReactDOM.Root>();
return {
// 渲染应用到指定 DOM 节点
render(info: {
dom: HTMLElement;
basename?: string;
memoryRoute?: { entryPath: string; }
}) {
const root = ReactDOM.createRoot(info.dom);
rootMap.set(info.dom, root);
root.render(
<BrowserRouter basename={info.basename}>
<App />
</BrowserRouter>
);
},
// 清理资源
destroy(info: { dom: HTMLElement }) {
const root = rootMap.get(info.dom);
root?.unmount();
rootMap.delete(info.dom);
},
}
}
消费端(宿主应用)
const RemoteApp = React.lazy(async () => {
// 加载远程模块
const module = await loadRemote('remote1/export-app');
const provider = module.default;
return {
default: () => {
const containerRef = useRef<HTMLDivElement>(null);
const providerRef = useRef<any>(null);
useEffect(() => {
if (containerRef.current) {
// 创建 provider 实例
const instance = provider();
providerRef.current = instance;
// 渲染远程应用
instance.render({
dom: containerRef.current,
basename: '/remote-app'
});
}
// 清理函数
return () => {
if (providerRef.current && containerRef.current) {
providerRef.current.destroy({
dom: containerRef.current
});
}
};
}, []);
return <div ref={containerRef} />;
}
};
});
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<RemoteApp />
</Suspense>
);
}
通过这种模式,Bridge 实现了框架无关的应用级模块加载,为微前端架构提供了坚实的技术基础。