> For AI agents: the complete documentation index is available at /zh/llms.txt, the full documentation bundle is available at /zh/llms-full.txt.

# 应用级别模块

Modern.js 提供了运行时 API，支持快速从应用中导出应用级别的 Module Federation 模块。

我们以 [使用模块联邦](/zh/guides/topic-detail/module-federation/usage.md) 创建的应用为例，进一步说明如何导入应用级别模块。

## 生产者导出模块

和直接导出组件级别的模块不同，我们需要为应用级别模块创建一个独立的入口来作为 `Module Federation` 的导出。

我们创建 `src/export-App.tsx` 文件：

:::note
这里可以是任意的文件名，Modern.js 没有做强制约定。
:::

```ts title="src/export-App.tsx"
import '@modern-js/runtime/registry/index'; // 这一行必须引入，它会默认导入微前端运行时依赖
import { render } from '@modern-js/runtime/browser';
import { createRoot } from '@modern-js/runtime/react';
import { createBridgeComponent } from '@module-federation/modern-js-v3/react-v19';

const ModernRoot = createRoot();
export const provider = createBridgeComponent({
  rootComponent: ModernRoot,
  render: (Component, dom) =>
    render(Component as React.ReactElement<{ basename: string }>, dom),
});

export default provider;
```

:::note
请根据你项目中使用的 React 版本来选择对应的导入路径：

- **React 19**：使用 `@module-federation/modern-js-v3/react-v19`
- **React 18**：使用 `@module-federation/modern-js-v3/react-v18`

你可以通过查看项目的 `package.json` 文件中的 `react` 依赖版本来确定应该使用哪个导入路径。
:::

该文件会将 `main` 入口的应用根组件传递给 Bridge API，并通过 Bridge 将调用渲染函数将其渲染到指定的节点上。

接下来，我们配置 `module-federation.config.ts`，将导出修改为 `src/export-App.tsx`：

```ts title="module-federation.config.ts"
import { createModuleFederationConfig } from '@module-federation/modern-js-v3';

export default createModuleFederationConfig({
  name: 'remote',
  manifest: {
    filePath: 'static',
  },
  filename: 'static/remoteEntry.js',
  exposes: {
    './app': './src/export-App.tsx',
  },
  shared: {
    react: { singleton: true },
    'react-dom': { singleton: true },
  },
});
```

:::info
[`createBridgeComponent`](https://module-federation.io/zh/guide/bridge/overview.html#%E6%A0%B8%E5%BF%83-api) 用于导出应用级别模块，Modern.js 相关 API 可以查看 [createRoot](/zh/apis/app/runtime/core/create-root.md)、[render](/zh/apis/app/runtime/core/render.md)。
:::

## 消费者使用模块

然后我们修改消费者配置，移除之前创建的的路由文件 `src/routes/remote/page.tsx`。

我们希望所有访问到 `/remote` 的路由都能被进入上述应用级别模块中，因此我们重新添加 `src/routes/remote/$.tsx`。

:::note
如果你还不了解 `$.tsx` 的能力，可以阅读 [通配路由](/zh/guides/basic-features/routes/routes.md#通配路由)。
:::

```tsx title="src/routes/remote/$.tsx"
import { createRemoteAppComponent } from '@module-federation/modern-js-v3/react';
import { loadRemote } from '@module-federation/modern-js-v3/runtime';

const ErrorBoundary = (info?: { error: { message: string } }) => {
  return (
    <div>
      <h2>This is ErrorBoundary Component, Something went wrong:</h2>
      <pre style={{ color: 'red' }}>{info?.error.message}</pre>
    </div>
  );
};
const Loading = <div>loading...</div>;
const RemoteApp = createRemoteAppComponent({
  loader: () => loadRemote('remote/app'),
  fallback: ErrorBoundary,
  loading: Loading,
});

export default RemoteApp;
```

:::info
[`createRemoteAppComponent`](https://module-federation.io/zh/guide/bridge/overview.html#%E6%A0%B8%E5%BF%83-api) 用于加载应用级别模块。
:::

## 启动应用

现在，生产者应用和消费者应用都已经搭建完毕，我们可以在本地运行 `modern dev` 启动两个应用。

启动后，消费者应用访问 `/remote` 路由时，会进入生产者应用中。访问 `http://localhost:8080/remote`，可以看到页面中已经包含了生产者的远程模块的完整页面。

你可以在生产者应用中，创建新的路由文件，并在代码中添加路由导航，可以发现这些功能也能够正常运行。

上述用例可以参考：[Modern.js & Module Federation 应用级别模块](https://github.com/web-infra-dev/modern.js/tree/main/examples/module-federation/app-export)。

## 相关文档

- [Module Federation Bridge](https://module-federation.io/zh/guide/bridge/overview)
