应用级别模块

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

我们以 使用模块联邦 创建的应用为例,进一步说明如何导入应用级别模块。

安装依赖

在原本应用的基础上,我们需要安装 @module-federation/bridge-react 依赖,用于使用 Bridge 加载应用级别模块。

npm
yarn
pnpm
bun
npm add @module-federation/bridge-react

生产者导出模块

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

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

NOTE

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

src/export-App.tsx
import '@modern-js/runtime/registry/main'; // 这一行必须引入,它会默认导入微前端运行时依赖
import { render } from '@modern-js/runtime/browser';
import { createRoot } from '@modern-js/runtime/react';
import { createBridgeComponent } from '@module-federation/bridge-react';

const ModernRoot = createRoot();
export const provider = createBridgeComponent({
  rootComponent: ModernRoot,
  render: (Component, dom) => render(Component, dom),
});

export default provider;

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

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

module-federation.config.ts
import { createModuleFederationConfig } from '@module-federation/modern-js';

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

createBridgeComponent 用于导出应用级别模块,Modern.js 相关 API 可以查看 createRootrender

消费者使用模块

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

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

NOTE

如果你还不了解 $.tsx 的能力,可以阅读 通配路由

src/routes/remote/$.tsx
import { createRemoteComponent } from '@module-federation/bridge-react';
import { loadRemote } from '@module-federation/modern-js/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 = createRemoteComponent({
  loader: () => loadRemote('remote/app'),
  fallback: ErrorBoundary,
  loading: Loading,
});

export default RemoteApp;
INFO

createRemoteComponent 用于加载应用级别模块。

启动应用

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

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

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

上述用例可以参考:Modern.js & Module Federation 应用级别模块

相关文档