导出应用

本章将介绍如何使用 createBridgeComponent 将您的 React 应用导出为可被远程加载的模块。

安装

npm
yarn
pnpm
npm install @module-federation/bridge-react@latest

基本使用

步骤 1: 创建导出入口

要导出一个 React 应用,您需要创建一个专门的导出文件,使用 createBridgeComponent 将应用包装为远程模块。

假设您的应用入口是 App.tsx,创建一个新文件 export-app.tsx

// ./src/export-app.tsx
import App from './App';
import { createBridgeComponent } from '@module-federation/bridge-react';

// 使用 createBridgeComponent 将 App 包装为远程模块并导出
export default createBridgeComponent({
  rootComponent: App
});

步骤 2: 配置 exposes 导出

接下来需要在构建工具中配置 Module Federation,将创建的导出文件暴露给其他应用使用。

构建工具支持

以下示例使用 Rsbuild 配置,请根据您使用的构建工具进行相应调整:

  • Rsbuild: @module-federation/rsbuild-plugin
  • Rspack: @module-federation/enhanced/rspack
  • Webpack: @module-federation/enhanced/webpack
  • Vite: @module-federation/vite
// rsbuild.config.ts
import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';

export default {
  plugins: [
    pluginModuleFederation({
      name: 'remote1',
      exposes: {
        './export-app': './src/export-app.tsx', // 导出应用类型远程模块
      },
    }),
  ],
};

Bridge Router 配置

React Bridge 提供了强大的路由协同能力,可根据当前路径动态为应用注入 basename 和路由上下文传递。

路由框架支持
  • Bridge Router 目前支持 React Router v5、v6、v7 版本的路由代理功能。

  • 暂不支持其他路由框架如 @tanstack/react-router,针对非 React Router 的应用,需要显示关闭 enableBridgeRouter,并自行处理路由逻辑。

启用 Bridge Router

// rsbuild.config.ts
import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';

export default {
  plugins: [
    pluginModuleFederation({
      name: 'remote1',
      exposes: {
        './export-app': './src/export-app.tsx',
      },
      bridge: {
        // 启用 Bridge Router 路由能力,默认为 true
        enableBridgeRouter: true, 
      }
    }),
  ],
};

配置说明

  • enableBridgeRouter: true (默认值) - 自动处理 basename 和路由协同,支持 React Router v5、v6、v7
  • enableBridgeRouter: false - 禁用 Bridge 默认的路由代理能力,用户需手动处理路由集成
重要

启用 Bridge Router 时,请勿将 react-router-dom 配置为 shared 依赖,否则会导致路由功能异常。

createBridgeComponent API 参考

函数签名

function createBridgeComponent<T = any>(
  bridgeInfo: Omit<ProviderFnParams<T>, 'createRoot'>
): () => {
  render(info: RenderParams): Promise<void>;
  destroy(info: DestroyParams): void;
}

ProviderFnParams<T>

桥接组件的配置参数:

interface ProviderFnParams<T> {
  // 根组件
  rootComponent: React.ComponentType<T>;
  
  // 自定义渲染函数(可选)
  render?: (App: React.ReactElement, id?: HTMLElement | string) => RootType | Promise<RootType>;
  
  // 自定义 createRoot 函数(可选,React 18+)
  createRoot?: (container: Element | DocumentFragment, options?: CreateRootOptions) => Root;
  
  // 默认的 createRoot 选项(React 18+)
  defaultRootOptions?: CreateRootOptions;
}

RenderParams

渲染参数接口:

interface RenderParams {
  moduleName?: string;
  basename?: string;
  memoryRoute?: {
    entryPath: string;
    initialState?: Record<string, unknown>;
  };
  dom: HTMLElement;                    // 渲染目标 DOM 元素
  rootOptions?: CreateRootOptions;     // React 18+ 的 createRoot 选项
  [key: string]: unknown;             // 其他自定义属性
}

DestroyParams

销毁参数接口:

interface DestroyParams {
  moduleName: string;
  dom: HTMLElement;
}

CreateRootOptions

React 18+ 的 createRoot 选项:

interface CreateRootOptions {
  identifierPrefix?: string;                                    // 标识符前缀
  onRecoverableError?: (error: unknown) => void;              // 可恢复错误处理
  transitionCallbacks?: unknown;                               // 过渡回调
}

高级用法示例

自定义渲染逻辑

// ./src/export-app.tsx
import App from './App';
import { createBridgeComponent } from '@module-federation/bridge-react';
import { createRoot } from 'react-dom/client';

export default createBridgeComponent({
  rootComponent: App,
  
  // 自定义渲染函数
  render: (App, container) => {
    const root = createRoot(container as HTMLElement, {
      identifierPrefix: 'my-app-'
    });
    root.render(App);
    return root;
  },
  
  // 默认的 createRoot 选项
  defaultRootOptions: {
    identifierPrefix: 'remote-app-',
    onRecoverableError: (error) => {
      console.error('Remote app recoverable error:', error);
    }
  }
});

支持多个导出

// ./src/export-app.tsx
import App from './App';
import Dashboard from './Dashboard';
import { createBridgeComponent } from '@module-federation/bridge-react';

// 导出主应用
export default createBridgeComponent({
  rootComponent: App
});

// 导出仪表板组件
export const dashboard = createBridgeComponent({
  rootComponent: Dashboard
});

对应的 Module Federation 配置:

// rsbuild.config.ts
export default {
  plugins: [
    pluginModuleFederation({
      name: 'remote1',
      exposes: {
        './export-app': './src/export-app.tsx',     // 主应用
        './dashboard': './src/export-app.tsx',      // 仪表板
      },
    }),
  ],
};

下一步

导出应用配置完成后,您可以继续阅读 加载远程应用 来了解如何在宿主应用中加载这个远程应用。