# Bridge 概览

## 介绍

`Bridge` 是 `Module Federation` 提供的工具函数，用于加载应用级别模块。
所谓 “应用级别模块”，即 能像应用一样运行的模块，具备应用的框架渲染能力及路由能力。
通过 `Bridge` 你可以在不同框架中渲染你的应用，并能保证应用间路由能协同工作。这对于微前端应用将非常有帮助。

:::tip
在阅读本章前，预设你已经了解：

- [如何消费和导出模块](../../guide/start/quick-start.mdx)
- [Module Federation Builder plugin](../../guide/basic/rspack.mdx)
- [Module Federation Runtime 的特点和能力](../../guide/basic/runtime.mdx)

:::

## 工具包

### @module-federation/bridge-react

`@module-federation/bridge-react` 适用于 React 框架类型，目前我们支持 React v16、v17、v18 版本。

在此工具包中我们提供 两个 API:

- createBridgeComponent

> 用于创建 React 应用类型模块导出，如果你的应用是 React 类型 且希望作为应用类型模块被另一个 MF 应用加载，那么你应该使用它为你的应用创造符合规范的导出。


- createRemoteComponent

> 用于在 React 应用中加载应用类型模块，所加载的模块必须被 `createBridgeComponent` 所包裹，`createRemoteComponent` 将自动在你的应用中创建渲染上下文以保证模块能正常工作。

`@module-federation/bridge-react` 的使用见 [Host demo](https://github.com/module-federation/core/tree/main/apps/router-demo/router-host-2000)、[Remote demo](https://github.com/module-federation/core/tree/main/apps/router-demo/router-remote2-2002)。


### @module-federation/bridge-vue3

`@module-federation/bridge-vue3` 适用于 Vue 框架类型，目前我们支持 Vue v3 版本。

在此工具包中我们提供 两个 API:

- createBridgeComponent

> 用于创建 Vue 应用类型模块导出，如果你的应用是 Vue v3 类型 且希望作为应用类型模块被另一个 MF 应用加载，那么你应该使用它为你的应用创造符合规范的导出。

- createRemoteComponent

> 用于在 Vue 应用中加载应用类型模块，所加载的模块必须被 `createBridgeComponent` 所包裹，`createRemoteComponent` 将自动在你的应用中创建渲染上下文以保证模块能正常工作。

## FAQ

### Why Bridge?

Bridge 主要用于解决两个问题：

* 跨应用框架（React、Vue）加载和渲染
* 支持加载带路由的模块（路由可以很好的协同工作）

这两个问题都是「微前端框架」里重要的特性

### 未提供对应框架的 bridge 如何解决？

目前 `Module Federation` 提供了官方的 bridge 工具包，如果你需要其他框架的 bridge 工具包，可以通过 [issue](https://github.com/module-federation/core/issues) 给我们提供反馈，也可以参考现有的 [`Bridge`](https://github.com/module-federation/core/blob/34ba220bcee3d032e4083aae37f802d1ed20d61b/packages/bridge/bridge-react) 如何实现.

`Bridge` 的实现非常简单，核心就是基于 `DOM` 渲染，下面是伪代码：

> 导出模块

```tsx
export default function () {
  const rootMap = new Map<any, ReactDOM.Root>();
  return {
    render(info: { dom: HTMLElement; basename?: string; memoryRoute?: { entryPath: string; } }) {
      const root = ReactDOM.createRoot(info.dom);
      rootMap.set(info.dom, root);
      root.render(
        <App />,
      );
    },
    destroy(info: { dom: HTMLElement }) {
      const root = rootMap.get(info.dom);
      root?.unmount();
    },
  }
}
```

> 加载模块

```tsx
const LazyComponent =  React.lazy(async () => {
  const m = await loadRemote('remote1/export-app');
  const providerInfo = m.default;
  return {
    default: () => {
      const rootRef = useRef(null);
      const providerInfoRef = useRef<any>(null);

      useEffect(() => {
        const providerReturn = providerInfo();
        providerInfoRef.current = providerReturn;
        providerReturn.render(renderProps);

        return () => {
          providerInfoRef.current?.destroy({
            dom: renderDom.current,
          });
        };
      }, []);
      return <div ref={rootRef}></div>;
    }
  };
});

function Component () {
  return (<React.Suspense fallback={<div>loading</div>}>
  <LazyComponent />
</React.Suspense>)
}
```

