# Metro Metro 模块联邦(Module Federation)为 React Native 移动开发带来了分布式架构的能力。 ## 概述 React Native 的模块联邦实现使用了自定义的 Metro 打包器集成,能够实现: - **微前端架构** —— 在 React Native 应用中实现微前端 - **代码共享** —— 在多个 React Native 应用之间共享代码 - **独立部署** —— 各个应用模块可以独立部署 - **运行时模块加载** —— 支持动态更新 > **注意**:Metro 打包器的模块联邦支持仍处于实验阶段,可能缺少部分功能或集成。依赖自定义 Metro 配置的项目或库目前尚不支持,可能无法正常工作。 ## 包 React Native 模块联邦生态系统由以下几个包组成: - `@module-federation/metro` - 与 Metro 的核心集成,用于启用模块联邦 - `@module-federation/metro-plugin-rnc-cli` - React Native CLI 集成 - `@module-federation/metro-plugin-rnef` - React Native Enterprise Framework 集成 ## 安装 在 React Native 项目中安装所需的包(使用你喜欢的包管理器): ```bash # 核心包(必需) pnpm add @module-federation/metro # 如果项目使用 React Native CLI pnpm add @module-federation/metro-plugin-rnc-cli # 如果项目使用 React Native Enterprise Framework (RNEF) pnpm add @module-federation/metro-plugin-rnef ``` ## 配置 使用 `withModuleFederation` 包装你的 Metro 配置以启用模块联邦。\ 你需要在所有联邦模块(宿主应用和子应用)的 Metro 配置中使用该方法。 ```javascript const { withModuleFederation } = require('@module-federation/metro'); const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); const config = {}; module.exports = withModuleFederation( mergeConfig(getDefaultConfig(__dirname), config), { // 模块联邦配置遵循官方文档格式: // https://module-federation.io/configure/index.html // 注意:部分功能在 React Native 环境中可能不可用 name: 'YourAppName', remotes: { // 定义远程应用(用于宿主应用) // remoteName: 'remoteName@http://localhost:8082/mf-manifest.json', }, exposes: { // 暴露模块(用于远程应用) // './Component': './src/Component.tsx', }, shared: { // 宿主应用应为所有共享依赖设置 eager: true react: { singleton: true, eager: true, requiredVersion: '19.1.0', version: '19.1.0', }, 'react-native': { singleton: true, eager: true, requiredVersion: '0.80.0', version: '0.80.0', }, }, }, { // 这些实验性标志用于修补旧版本包 // 如果项目使用受支持的 React Native 和 Metro 版本,可以省略 flags: { // 启用修补 React Native 的 HMR Client unstable_patchHMRClient: true, // 启用修补 React Native CLI unstable_patchInitializeCore: true, // 启用修补 Metro 的运行时 require unstable_patchRuntimeRequire: true, }, } ); ``` ### 应用异步边界设置 使用 `withAsyncStartup` 包装主 App 组件以启用模块联邦运行时。\ 这会创建一个异步边界,确保在渲染应用组件之前正确初始化模块联邦运行时。 ```javascript import { withAsyncStartup } from '@module-federation/runtime'; import { AppRegistry } from 'react-native'; // 使用 withAsyncStartup 创建异步边界 // 传入获取 App 组件的函数 // 可选地传入获取备用组件的函数 const WrappedApp = withAsyncStartup( () => require('./App'), () => require('./Fallback') // 可选备用组件 ); AppRegistry.registerComponent('YourAppName', WrappedApp); ``` `withAsyncStartup` 的作用: - 在渲染应用前等待模块联邦运行时初始化 - 使用 React Suspense 处理异步加载 - 可选地接受一个备用组件,在初始化期间显示 ## 使用模式 ### 宿主应用 宿主应用从其他应用中消费远程模块: ```javascript // 宿主应用 metro.config.js module.exports = withModuleFederation( mergeConfig(getDefaultConfig(__dirname), config), { name: 'HostApp', remotes: { 'mini-app': 'miniApp@http://localhost:8082/mf-manifest.json', 'another-app': 'anotherApp@http://192.168.1.100:8083/mf-manifest.json', }, shared: { react: { singleton: true, eager: true }, 'react-native': { singleton: true, eager: true }, }, } ); ``` ### 远程应用(子应用) 远程应用暴露模块供宿主应用使用: ```javascript // 远程应用 metro.config.js module.exports = withModuleFederation( mergeConfig(getDefaultConfig(__dirname), config), { name: 'MiniApp', exposes: { './Screen': './src/Screen.tsx', './Component': './src/Component.tsx', }, shared: { react: { singleton: true, eager: true }, 'react-native': { singleton: true, eager: true }, }, } ); ``` ## CLI 命令 React Native CLI 集成提供了额外的命令来打包联邦应用: ### 打包宿主应用 打包消费远程模块的宿主应用: ```bash # iOS 打包 react-native bundle-mf-host --entry-file index.js --platform ios # Android 打包 react-native bundle-mf-host --entry-file index.js --platform android ``` ### 打包远程应用 打包暴露模块的远程应用(子应用): ```bash # iOS 打包 react-native bundle-mf-remote --platform ios # Android 打包 react-native bundle-mf-remote --platform android ``` 这些命令支持与标准 `react-native bundle` 命令相同的所有选项。 > **注意**:这些命令由 `@module-federation/metro-plugin-rnc-cli` 包提供。 ## React Native Enterprise Framework (RNEF) 集成 如果项目使用 [React Native Enterprise Framework (RNEF)](https://github.com/callstack/react-native-enterprise-framework),请在 `rnef.config.mjs` 中添加模块联邦插件: ```javascript import { pluginMetroModuleFederation } from '@module-federation/metro-plugin-rnef'; import { platformAndroid } from '@rnef/platform-android'; import { platformIOS } from '@rnef/platform-ios'; import { pluginMetro } from '@rnef/plugin-metro'; /** @type {import('@rnef/config').Config} */ export default { bundler: pluginMetro(), platforms: { ios: platformIOS(), android: platformAndroid(), }, plugins: [pluginMetroModuleFederation()], }; ``` ## API 参考 ### `withModuleFederation(metroConfig, federationConfig, options?)` 包装 Metro 配置以启用模块联邦。 #### 参数 - `metroConfig` (MetroConfig) - 现有的 Metro 配置 - `federationConfig` (FederationConfig) - 模块联邦配置 - `options` (Options) - 可选配置,用于实验性功能 #### FederationConfig 接口 ```typescript export interface ModuleFederationConfig { name: string; filename?: string; remotes?: Record<string, string>; exposes?: Record<string, string>; shared?: Shared; shareStrategy?: 'loaded-first' | 'version-first'; plugins?: string[]; } ``` #### SharedConfig 接口 ```typescript export interface SharedConfig { singleton: boolean; eager: boolean; version: string; requiredVersion: string; import?: false; } ``` ## 示例与最佳实践 配置遵循标准的 [模块联邦配置格式](https://module-federation.io/configure/)。\ 关于模块联邦的概念、配置选项和使用模式的完整信息,请参考官方 [模块联邦文档](https://module-federation.io/)。 要查看可运行的示例和详细实现指南,请访问 [Module Federation Metro 仓库](https://github.com/module-federation/metro),其中包含多个示例应用,展示了不同的使用模式和集成方式。