在Expo开发过程中,开发者可能会遇到需要超出Expo SDK提供功能的场景。这时需要使用Expo Development Build或Eject流程来扩展应用能力。
Expo Development Build:
Development Build是推荐的扩展方式,它允许在保持Expo工作流的同时添加自定义原生代码。
特点:
- 保留Expo的开发体验和OTA更新能力
- 可以添加自定义原生模块
- 支持所有Expo SDK功能
- 更容易维护和升级
创建Development Build:
bash# 安装EAS CLI npm install -g eas-cli # 配置EAS eas build:configure # 创建开发构建 eas build --profile development --platform android
配置文件:
在eas.json中配置development profile:
json{ "build": { "development": { "developmentClient": true, "distribution": "internal" } } }
添加自定义原生模块:
- 创建原生模块目录:
shellmy-app/ ├── android/ │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── myapp/ │ └── CustomModule.java ├── ios/ │ └── myapp/ │ └── CustomModule.m
- Android模块示例:
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 { // 自定义原生逻辑 promise.resolve("Success"); } catch (Exception e) { promise.reject("Error", e.getMessage()); } } }
- iOS模块示例:
objc#import <React/RCTBridgeModule.h> @interface RCT_EXTERN_MODULE(CustomModule, NSObject) RCT_EXTERN_METHOD(customMethod:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) @end
- JavaScript中使用:
typescriptimport { NativeModules } from 'react-native'; const { CustomModule } = NativeModules; CustomModule.customMethod() .then(result => console.log(result)) .catch(error => console.error(error));
Eject流程:
Eject会将Expo项目转换为纯React Native项目,完全脱离Expo生态系统。
特点:
- 完全控制原生代码
- 无法使用Expo Go
- 失去OTA更新能力
- 需要自己管理原生依赖
Eject步骤:
bash# Eject项目 npx expo eject # 选择模板 # - Bare: 纯React Native项目 # - ExpoKit: 保留部分Expo功能(已弃用)
何时使用Development Build:
- 需要添加自定义原生模块
- 需要使用第三方原生库
- 需要访问特定的原生API
- 希望保持Expo的开发体验
何时使用Eject:
- 需要完全控制原生代码
- 项目不再需要Expo的任何功能
- 需要深度定制原生层
- 团队有丰富的原生开发经验
最佳实践:
-
优先使用Development Build:除非有特殊需求,否则不要Eject
-
模块化原生代码:将原生代码组织成独立的模块,便于维护
-
版本控制:将原生代码纳入Git版本控制
-
文档记录:详细记录自定义模块的使用方法和API
-
测试覆盖:为原生模块编写单元测试和集成测试
-
性能监控:监控原生模块的性能影响
常见问题:
-
模块注册:确保原生模块正确注册到React Native桥接
-
权限配置:在
app.json中添加必要的权限声明 -
依赖冲突:注意原生依赖之间的版本兼容性
-
平台差异:处理Android和iOS之间的API差异
-
调试困难:使用Flipper等工具调试原生代码
回退到Expo:
如果Development Build或Eject后出现问题,可以创建新的Expo项目并迁移JavaScript代码。
选择Development Build还是Eject取决于项目需求和团队技术栈,大多数情况下Development Build是更好的选择。