Expo + React Native封装第三方原生库的正确方法及路径咨询
Expo + React Native 封装第三方原生库的正确方案与最优路径
一、最优实现路径
你的尝试结果已经给出了明确答案:基于纯Expo项目 + Expo Module是适配Expo生态的最优方案。原因很简单:
- 纯Expo项目(未预构建)不支持直接使用Turbo Module,Expo Go的运行环境无法兼容Turbo Module的底层机制
- Expo Module是Expo官方推出的原生模块开发标准,完美适配Expo预构建、EAS构建等工作流,无需转回纯React Native Module
二、iOS第三方依赖的正确添加方式
不需要给Expo Module的ios目录添加Podfile,所有iOS第三方依赖都应该在模块的AwesomeModule.podspec中声明,具体操作如下:
- 打开
awesome-module/ios/AwesomeModule.podspec - 在文件中添加
s.dependency字段声明第三方库,比如要引入SDWebImage:
# 示例:添加SDWebImage依赖 s.dependency 'SDWebImage', '~> 5.18'
- 回到主项目(AwesomeApp),执行
npx expo install awesome-module安装模块,之后运行npx expo prebuild或cd ios && pod install,主项目会自动拉取模块声明的所有iOS依赖
不要在主项目的Podfile中直接添加模块的依赖,模块应该是自包含的,这样其他项目复用该模块时才能自动获取所需依赖。
三、Android第三方依赖的添加方式
Android端的第三方依赖需要在模块的android/build.gradle中声明:
dependencies { // 示例:添加OkHttp依赖 implementation 'com.squareup.okhttp3:okhttp:4.12.0' }
主项目在安装模块后,会自动同步该依赖到自身的构建流程中。
四、完整实现示例(简化版)
以封装iOS的MBProgressHUD和Android的加载弹窗为例,暴露showLoading方法给JS层:
1. 创建Expo Module
npx create-expo-module AwesomeLoadingModule
2. iOS依赖配置(podspec)
在AwesomeLoadingModule.podspec中添加:
s.dependency 'MBProgressHUD', '~> 1.2.0'
3. iOS原生代码实现(AwesomeLoadingModule.m)
#import <MBProgressHUD/MBProgressHUD.h> #import "AwesomeLoadingModule.h" @implementation AwesomeLoadingModule EXPO_EXPORT_MODULE(AwesomeLoadingModule); EXPO_EXPORT_METHOD_AS(showLoading, showLoading:(NSString *)message resolve:(EXPromiseResolveBlock)resolve reject:(EXPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ UIViewController *rootVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:rootVC.view animated:YES]; hud.label.text = message; }); resolve(@"Loading shown"); } @end
4. Android原生代码实现(AwesomeLoadingModule.kt)
package expo.modules.awesomeloadingmodule import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition import android.app.ProgressDialog import android.content.Context class AwesomeLoadingModule : Module() { private val context: Context get() = appContext.reactContext ?: throw IllegalStateException("React context is null") override fun definition() = ModuleDefinition { Name("AwesomeLoadingModule") Function("showLoading") { message: String -> val progressDialog = ProgressDialog(context) progressDialog.setMessage(message) progressDialog.show() "Loading shown" } } }
5. JS层暴露与使用
在模块的src/AwesomeLoadingModule.ts中:
import { requireNativeModule } from 'expo-modules-core'; export default requireNativeModule('AwesomeLoadingModule');
主项目中安装模块后调用:
import AwesomeLoadingModule from 'awesome-loading-module'; // 调用原生方法 AwesomeLoadingModule.showLoading("加载中...");
五、常见误区澄清
- 不要给Expo Module的iOS目录手动添加Podfile:模块是作为Pod被主项目引用的,依赖声明必须放在podspec中,保证模块的可移植性
- 无需转回纯React Native Module:Expo Module完全支持封装第三方原生库,且兼容Expo的所有核心功能,是Expo生态下的标准方案
内容的提问来源于stack exchange,提问作者Ry Lowry
相关产品推荐
相关产品推荐

