React Native, Metro and Module Federation
This guide will explain how to build a React Native app with Metro bundler that uses Module Federation to share code between apps. This approach enables you to create micro-frontend architectures in React Native applications, allowing teams to develop, deploy, and scale mini-applications independently.
- Finished our Get Started guide
- A registered account on Zephyr Cloud
- npm >=10
- node >=18
- ruby >= 3.3.2
Overview
Module Federation with Metro bundler in React Native provides several key advantages:
- Independent Development: Teams can develop mini-applications in isolation with their own release cycles
- Code Sharing: Efficient sharing of common dependencies and utilities across applications
- Runtime Loading: Dynamic loading of mini-applications without requiring app store updates
- Scalability: Easy addition of new features and micro-frontends as your application grows
- Team Autonomy: Different teams can work on different parts of the application independently
Architecture Considerations
When implementing Module Federation with Metro in React Native, consider these architectural patterns:
- Host Application: The main React Native app that loads and orchestrates mini-applications
- Mini Applications: Self-contained React Native applications that expose specific functionality
- Shared Dependencies: Common libraries and utilities shared between host and mini-applications
Creating Your Applications
Project Structure
Your project structure should look like this:
Creating a New React Native Application
If you're starting from scratch, create both the host and mini applications:
Create a new React Native host application:
Create a new React Native mini application:
Modifying an Existing React Native Application
If you have existing React Native applications, you can convert them to use Module Federation. Install the required dependencies in both host and mini applications:
Configuring the Mini Application
The mini application is a self-contained React Native app that exposes specific functionality to be consumed by the host application. This section covers the essential configuration steps.
Understanding Mini Application Configuration
Mini applications in Module Federation work as "remotes" that expose modules to be consumed by host applications. Key aspects include:
- Exposed Modules: Components, utilities, or entire screens that can be loaded by the host
- Shared Dependencies: Libraries that are shared between host and mini applications
- Bundle Configuration: How the application is bundled and served
Step 1: Configure Metro for Module Federation
Create or modify your metro.config.js file in the mini application:
Configuration Breakdown
- name: Unique identifier for your mini application
- filename: The bundle filename that will be generated
- exposes: Modules to expose to host applications (key is the public path, value is the source path)
- shared: Dependencies shared with the host application
- singleton: Ensures only one instance is loaded
- eager: Controls whether the dependency is loaded immediately
- requiredVersion: Version constraint for the shared dependency
- import: Whether to import the dependency (set to false for React Native)
- shareStrategy:
'version-first'prioritizes version compatibility
Step 2: Configure React Native CLI
Create or modify your react-native.config.js file to enable uploading mini application bundles to Zephyr Cloud:
Why This Configuration?
This configuration adds a custom React Native CLI command that:
- Handles Module Federation bundling
- Integrates with Zephyr Cloud for asset upload
- Updates the Module Federation manifest
- Enables deployment to Zephyr's edge network
Step 3: Create an Exposed Component
Create a component in your mini application that will be exposed to the host:
Step 4: Bundle Your Mini Application
Once configured, bundle your mini application for different platforms:
After bundling, configure your mini app environments and tags in the Tags & Environments section of your Zephyr Cloud dashboard.
Configuring the Host Application
The host application is the main React Native app that loads and orchestrates mini-applications. It acts as a "consumer" in the Module Federation architecture.
Understanding Host Application Configuration
The host application configuration differs from mini-applications in several key ways:
- Remotes Configuration: Defines which mini-applications to load and from where
- Eager Loading: Host applications typically eager-load shared dependencies
- Runtime Plugins: Can include custom runtime logic for module loading
- Share Strategy: Uses
'loaded-first'strategy to prioritize already loaded dependencies
Step 1: Configure Metro for the Host
Create or modify your metro.config.js file in the host application:
Configuration Breakdown
- name: Unique identifier for your host application
- remotes: Mini-applications to load
- Key is the local name you'll use to import
- Value is the remote entry URL (Zephyr will resolve this to the cloud URL)
- shared: Dependencies shared with mini-applications
- eager: true: Host loads these dependencies immediately
- shareStrategy:
'loaded-first'prioritizes already loaded dependencies - plugins: Optional runtime plugins for custom logic
Step 2: Configure Zephyr Dependencies
To enable Zephyr Cloud integration, add the zephyr:dependencies field to your package.json:
Environment Configuration
- miniApp: The name of the mini-application (must match the name in metro.config.js)
- zephyr:miniApp@yourEnvironment: References the mini-app from a specific Zephyr environment
- Replace
yourEnvironmentwith your actual environment name (e.g.,staging,production)
For more information about managing dependencies, see Remote Dependencies.
Step 3: Load Mini Application in Your Code
Now you can use the mini application in your host app:
Always wrap lazy-loaded components with Suspense to handle loading states gracefully.
Running Your Application
Once both host and mini applications are configured:
Step 1: Start the Metro Bundler
In your host application directory:
Step 2: Run on iOS
Open a new terminal and run:
Step 3: Run on Android
Open a new terminal and run:
During development, the host will load mini-applications from the URLs specified in your Metro configuration. In production, Zephyr will automatically resolve these to your deployed versions based on your environment configuration.
Best Practices
Shared Dependencies
Carefully manage shared dependencies to avoid version conflicts:
Error Handling
Implement proper error boundaries for mini-applications:
Platform-Specific Code
Handle platform differences in your mini-applications:
Troubleshooting
Mini Application Not Loading
If your mini application fails to load:
- Verify the remote URL in metro.config.js
- Check that the mini application was bundled successfully
- Ensure the mini application is deployed to Zephyr Cloud
- Verify network connectivity and CORS settings
Version Conflicts
If you encounter dependency version conflicts:
- Ensure shared dependencies have matching version ranges
- Use
singleton: truefor critical dependencies like React - Check the Metro bundler logs for specific version mismatches
Build Failures
Common build issues and solutions:
- Module not found: Verify the exposed path in the mini app's metro.config.js
- Bundle size too large: Review shared dependencies and optimize imports
- Cache issues: Clear Metro cache with
npx react-native start --reset-cache
Next Steps
Now that you have Module Federation working with Metro, explore these advanced topics:
- Explore our example repository for complete working examples
- Learn about Tags & Environments for managing different deployment stages
- Check out Remote Dependencies for advanced dependency configuration
- Review End-to-End Testing for testing federated applications
- Understand Versioning and Tags for managing deployments
- Set up CI/CD pipelines for automated deployments with Personal token
- Set up CI/CD pipelines for automated deployments with Server token