During Expo development, developers may encounter scenarios where they need to go beyond the functionality provided by the Expo SDK. In such cases, Expo Development Build or the Eject process can be used to extend app capabilities.
Expo Development Build:
Development Build is the recommended extension method, allowing you to add custom native code while maintaining the Expo workflow.
Features:
- Retains Expo development experience and OTA update capabilities
- Can add custom native modules
- Supports all Expo SDK features
- Easier to maintain and upgrade
Creating Development Build:
bash# Install EAS CLI npm install -g eas-cli # Configure EAS eas build:configure # Create development build eas build --profile development --platform android
Configuration File:
Configure development profile in eas.json:
json{ "build": { "development": { "developmentClient": true, "distribution": "internal" } } }
Adding Custom Native Modules:
- Create native module directory:
shellmy-app/ ├── android/ │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── myapp/ │ └── CustomModule.java ├── ios/ │ └── myapp/ │ └── CustomModule.m
- Android module example:
javapackage com.myapp; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.Promise; public class CustomModule extends ReactContextBaseJavaModule { public CustomModule(ReactApplicationContext context) { super(context); } @Override public String getName() { return "CustomModule"; } @ReactMethod public void customMethod(Promise promise) { try { // Custom native logic promise.resolve("Success"); } catch (Exception e) { promise.reject("Error", e.getMessage()); } } }
- iOS module example:
objc#import <React/RCTBridgeModule.h> @interface RCT_EXTERN_MODULE(CustomModule, NSObject) RCT_EXTERN_METHOD(customMethod:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) @end
- Usage in JavaScript:
typescriptimport { NativeModules } from 'react-native'; const { CustomModule } = NativeModules; CustomModule.customMethod() .then(result => console.log(result)) .catch(error => console.error(error));
Eject Process:
Eject converts an Expo project to a pure React Native project, completely脱离 the Expo ecosystem.
Features:
- Complete control over native code
- Cannot use Expo Go
- Loses OTA update capabilities
- Need to manage native dependencies yourself
Eject Steps:
bash# Eject project npx expo eject # Choose template # - Bare: Pure React Native project # - ExpoKit: Retain some Expo features (deprecated)
When to Use Development Build:
- Need to add custom native modules
- Need to use third-party native libraries
- Need to access specific native APIs
- Want to maintain Expo development experience
When to Use Eject:
- Need complete control over native code
- Project no longer needs any Expo features
- Need deep customization of native layer
- Team has rich native development experience
Best Practices:
-
Prioritize Development Build: Don't eject unless there are special requirements
-
Modularize Native Code: Organize native code into independent modules for easier maintenance
-
Version Control: Include native code in Git version control
-
Document: Document usage methods and APIs for custom modules in detail
-
Test Coverage: Write unit tests and integration tests for native modules
-
Performance Monitoring: Monitor performance impact of native modules
Common Issues:
-
Module Registration: Ensure native modules are properly registered to the React Native bridge
-
Permission Configuration: Add necessary permission declarations in
app.json -
Dependency Conflicts: Pay attention to version compatibility between native dependencies
-
Platform Differences: Handle API differences between Android and iOS
-
Debugging Difficulties: Use tools like Flipper to debug native code
Rolling Back to Expo:
If issues occur after Development Build or Eject, you can create a new Expo project and migrate the JavaScript code.
Choosing between Development Build and Eject depends on project requirements and team technical stack, but in most cases Development Build is the better choice.