A comprehensive React Native super app demonstrating Module Federation V2 with Re.Pack 5.x, showcasing micro-frontend architecture patterns and advanced bundle management.
- Architecture Overview
- Key Learnings
- Dependencies & Tooling
- Project Structure
- Setup & Installation
- Development Workflow
- Configuration Deep Dive
- Troubleshooting
- Performance Optimization
This project demonstrates a Module Federation V2 super app architecture with the following micro-frontends:
graph TB
Host[Travel Host App<br/>Port: 8081] --> Weather[Weather MF<br/>Port: 9000]
Host --> Destinations[Destinations MF<br/>Port: 9001]
Host --> Search[Search MF<br/>Port: 9002]
Host --> Photos[Photos MF<br/>Port: 9003]
Host --> Core[travel-core<br/>Shared Package]
Weather --> Core
Destinations --> Core
Search --> Core
Photos --> Core
Host --> SDK[travel-sdk<br/>Dependency Manager]
- β Manifest-Based Resolution: Automatic remote discovery via JSON manifests
- β
Platform Agnostic: Dynamic
${platform}interpolation for iOS/Android - β Zero Configuration: No custom resolvers or URL management needed
- β Version Management: Built-in caching and dependency sharing
- β Developer Experience: Hot reloading across micro-frontends
- β Type Safety: Enhanced TypeScript integration
MF V2's manifest system (mf-manifest.json) provides:
- Automatic remote discovery
- Platform-specific resolution (
${platform}interpolation) - Built-in version management
- Zero configuration complexity
// Simple, declarative configuration
remotes: {
TravelWeather: `TravelWeather@http://localhost:9000/${platform}/mf-manifest.json`,
TravelDestinations: `TravelDestinations@http://localhost:9001/${platform}/mf-manifest.json`
}The combination delivers:
- Fast builds with Rspack's Rust-based bundling
- Hot reloading across micro-frontends
- Tree shaking for optimal bundle sizes
- Hermes bytecode support for production
The enhanced plugin provides:
- Manifest-based resolution: No manual URL management
- Dynamic type hinting: Better TypeScript integration
- Runtime plugin system: Extensible architecture
- Built-in optimization: Automatic dependency sharing
| Package | Version | Purpose |
|---|---|---|
@callstack/repack |
5.2.5 |
React Native bundling with Module Federation |
@module-federation/enhanced |
2.5.1 |
Enhanced MF features |
@module-federation/runtime |
2.5.1 |
MF runtime (registerRemotes, plugins) |
@rspack/core |
^1.4.0 |
Fast Rust-based bundler |
@swc/helpers |
0.5.15 |
SWC transformation helpers |
| Tool | Purpose | Configuration |
|---|---|---|
| pnpm | Package manager with workspace support | pnpm-workspace.yaml |
| concurrently | Multi-process dev server (pnpm start) |
root package.json |
- React Native:
0.80.2 - React:
19.1.0 - Expo:
~53.0.22 - Node.js:
>=22(engineStrict;22.18+recommended for native TypeScript rspack configs; older 22.x uses jiti automatically)
travel-app-repack-example/
βββ π± apps/ # Micro-frontend applications
β βββ travel-host/ # Main host app (Port: 8081)
β β βββ rspack.config.ts # MF V2 host (runtime remotes)
β β βββ src/federation/ # Dynamic remote registration
β βββ travel-weather/ # Weather MF (Port: 9000)
β βββ travel-destinations/ # Destinations MF (Port: 9001)
β βββ travel-search/ # Search MF (Port: 9002)
β βββ travel-photos/ # Photos MF (Port: 9003)
βββ π¦ packages/ # Shared packages
β βββ travel-core/ # Core utilities & components
β β βββ src/components/ # Shared UI components
β β βββ src/context/ # Global state management
β β βββ src/utils/ # Utility functions
β βββ travel-sdk/ # Dependency management SDK (plain JS, no build step)
β βββ index.js # Public exports
β βββ lib/dependencies.json # Centralized dependency versions
β βββ lib/sharedDeps.js # MF shared dependencies factory
β βββ lib/createRspackConfig.js # Rspack factory for host/remotes
β βββ lib/remotes.config.js # Static remote metadata (slug, ports, UI)
β βββ lib/remote-registry.dev.json # Generated dev registry (committed)
β βββ lib/remote-registry.prod.json # Bundled prod fallback (generated)
β βββ lib/remoteProfiles.js # buildRegistryJson, buildHostRemotes
β βββ lib/writeRemoteArtifacts.js
βββ remotes-dist/ # Pre-built remote bundles + registry
βββ scripts/ # build-remotes, generate-registry, serve-remotes
βββ βοΈ Configuration Files
β βββ pnpm-workspace.yaml # PNPM workspace definition
β βββ tsconfig.json # Root TypeScript config
βββ π docs/ # Documentation
# Required versions
node --version # >= 22.0.0
pnpm --version # >= 10.10.0# 1. Clone and install dependencies
git clone <repository-url>
cd travel-app-repack-example
pnpm install
# CI uses frozen lockfile: pnpm install:ci
# Supply-chain hardening: see docs/SECURITY-PNPM.md
# 2. iOS setup (if developing for iOS)
cd apps/travel-host/ios
pod install
cd ../../..
# 3. Start all micro-frontends
pnpm start # concurrently: host + 4 remotes
# Alternative: Start individually
pnpm start:travel-host # Host app
pnpm start:travel-weather # Weather MF
pnpm start:travel-destinations # Destinations MF
pnpm start:travel-search # Search MF
pnpm start:travel-photos # Photos MF# iOS
pnpm run:travel-host:ios
# Android
pnpm run:travel-host:android# Start all services (host + remotes)
pnpm startThis launches:
- Host app on port 8081
- Weather MF on port 9000
- Destinations MF on port 9001
- Search MF on port 9002
- Photos MF on port 9003
# Terminal 1: Host
pnpm start:travel-host
# Terminal 2: Specific micro-frontend
pnpm start:travel-weatherProfile is derived automatically:
| Mode | Runtime | MF URLs | Registry |
|---|---|---|---|
| dev | __DEV__ |
Live bundlers :9000-9003 (build-time rspack) |
Bundled remote-registry.dev.json |
| prod | release build | CDN / :4100 fallback |
fetch(remote-registry.json) + registerRemotes() |
Dev MF URLs use localhost (simulator). Prod registry URL: app.config.ts β extra.remoteRegistryUrl.
# Dev (default debug build)
pnpm start
# Prod-like local test (release build + static bundles)
pnpm build:remotes:ios # all remotes
pnpm build:remotes:ios -- weather # one remote (also: search, TravelWeather, etc.)
pnpm serve:remotes # :4100
pnpm run:travel-host:ios:release
# Regenerate registry only (reads version from each micro-app package.json)
pnpm generate:registry
# Do NOT use `expo run:ios --configuration Release` β Expo pre-bundles with Metro
# and cannot resolve federated imports (e.g. TravelPhotos/PhotosScreen).
# Release uses react-native CLI + Re.Pack (see apps/travel-host/ios/.xcode.env.updates).Each micro-app version lives in its own package.json. Run pnpm generate:registry (or build:remotes) to refresh remote-registry.dev.json and remotes-dist/remote-registry.json.
# 1. Bump version in the micro-app
# apps/travel-weather/package.json β "version": "1.0.2"
# 2. Build bundle(s) and regenerate registry
pnpm build:remotes:ios -- weather
# 3. Rebuild host release and reopen the app
pnpm run:travel-host:ios:releaseOn app start, checkForUpdates() compares the installed bundle version (bundle_installed_* in AsyncStorage) with the registry and invalidates ScriptManager cache when they differ.
Each micro-frontend can run independently:
pnpm start:standalone:travel-weather// apps/travel-host/rspack.config.ts β remotes registered at runtime
new Repack.plugins.ModuleFederationPluginV2({
name: 'TravelHost',
dts: false,
remotes: {},
shared: getSharedDependencies({ eager: true }),
runtimePlugins: ['./mf-fetch-plugin.ts'],
});
// apps/travel-host/src/federation/initRemotes.ts
registerRemotes(registry.remotes); // from remote-registry.json or dev config// apps/travel-weather/rspack.config.ts β via createRemoteRspackConfig from travel-sdk
export default createRemoteRspackConfig({
mfName: 'TravelWeather',
exposes: {
'./App': './src/navigation/MainNavigator',
},
shared: getSharedDependencies({ eager: false }),
});// rnef.config.mjs
export default {
bundler: pluginRepack(),
platforms: {
ios: platformIOS(),
android: platformAndroid(),
},
remoteCacheProvider: null,
};// packages/travel-sdk/lib/sharedDeps.js
export default function getSharedDependencies({ eager = true } = {}) {
const dependencies = /* read from ./dependencies.json */;
const shared = Object.entries(dependencies).map(([dep, { version }]) => {
return [dep, { singleton: true, eager, requiredVersion: version, version }];
});
return Object.fromEntries(shared);
}Replaced by pnpm workspaces. Root scripts orchestrate tasks across packages:
{
"typecheck": "pnpm -r --if-present run typecheck",
"lint:check": "pnpm -r --if-present run lint",
"test": "pnpm -r --if-present run test"
}pnpm start uses concurrently to run host and remotes in one terminal:
pnpm start
# Or start individually:
pnpm start:travel-host
pnpm start:travel-weatherIssue: Remote manifests fail to load
Debug Steps:
# Check if manifest is accessible
curl http://localhost:9000/android/mf-manifest.json
# Verify manifest structure
cat apps/travel-weather/dist/android/mf-manifest.jsonSolution: Ensure remote is running and ports are correct
Issue: Multiple services trying to use the same port
Solution: Check port allocation in package.json scripts:
- Host: 8081
- Weather: 9000
- Destinations: 9001
- Search: 9002
- Photos: 9003
Issue: Incorrect platform detection in manifest URLs
Solution: Verify platform interpolation:
// Ensure ${platform} resolves correctly
remotes: {
TravelWeather: `TravelWeather@http://localhost:9000/${platform}/mf-manifest.json`;
}Issue: Version conflicts between host and remotes
Solution: Use centralized dependency management:
// packages/travel-sdk/lib/dependencies.json
{
"react": { "version": "19.0.0" },
"react-native": { "version": "0.79.5" }
}Issue: Remote bundles fail to load
Debug Steps:
# Check manifest accessibility
curl http://localhost:9000/android/mf-manifest.json
# Monitor network requests
adb logcat | grep -i "module federation"
# Enable MF debugging
console.log('MF V2 Debug:', window.__FEDERATION__);// Enable Hermes bytecode for production
new Repack.plugins.HermesBytecodePlugin({
enabled: mode === 'production',
test: /\.(js)?bundle$/,
exclude: /index.bundle$/,
});// Host: Eager loading for core dependencies
shared: getSharedDependencies({ eager: true });
// Remotes: Lazy loading for optimal startup
shared: getSharedDependencies({ eager: false });Use Re.Pack / CI cache for bundle:ios and bundle:remote:* outputs under each app's build/ directory.
- Centralize shared dependencies in
travel-sdk - Use exact versions for consistency
- Regular dependency audits
- Use
pnpm startfor orchestrated development (or individualstart:travel-*scripts) - Enable hot reloading for fast iterations
- Implement proper error boundaries
- Keep micro-frontends loosely coupled
- Share common UI through
travel-core - Use TypeScript for type safety
- Lazy load non-critical micro-frontends
- Optimize bundle sizes with tree shaking
- Use Hermes for production builds
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
Built with β€οΈ using Module Federation V2, Re.Pack 5.x, and React Native 0.80.2