Expo React Native组件打包为AAR及原生Android/iOS集成问题求助
Expo React Native组件打包为AAR及原生Android/iOS集成问题求助
我完全理解你现在的困扰——把Expo RN组件封装成可复用的原生库确实比普通RN项目复杂不少,尤其是处理依赖和打包AAR这块踩坑点特别多。我来给你一步步拆解可行的解决方案:
一、先搞定Expo项目的原生化预准备
因为Expo有自己的打包和依赖管理逻辑,不能直接用原生RN的react-native bundle命令,得先把项目转换成可原生编译的结构:
- 运行
npx expo prebuild生成原生Android和iOS目录,这一步会自动处理Expo依赖的原生配置 - 确保你的
HelloWorldWidget组件已经在RN端注册为可被原生调用的模块:
// 项目根目录index.js import { AppRegistry } from 'react-native'; import HelloWorldWidget from './path/to/HelloWorldWidget'; // 注册组件,原生端会用这个名称调用 AppRegistry.registerComponent('HelloWorldWidget', () => HelloWorldWidget);
二、Android端:打包可复用AAR的正确姿势(解决依赖缺失)
1. 新建Android Library模块
不要直接修改默认的app模块,而是在Android项目里新建一个Android Library(比如命名为rn-widget-library)——这是打包AAR的基础,因为只有Library模块才能导出可复用的AAR。
2. 配置依赖与资源
- 在Library模块的
build.gradle里,声明所有需要的依赖(包括RN核心、hermes、react-native-svg等),并开启依赖传递,这样宿主app引入AAR时会自动拉取这些依赖:
// rn-widget-library/build.gradle dependencies { // RN核心依赖,版本和你项目里的保持一致 implementation "com.facebook.react:react-native:0.72.+" implementation "com.facebook.hermes:hermes-android:0.72.+" // 第三方库依赖,比如react-native-svg implementation project(':react-native-svg') } // 开启依赖传递,让宿主app自动获取所需依赖 configurations.all { transitive = true }
- 用Expo的命令生成正确的JS Bundle和资源,替代原生RN的bundle命令:
npx expo export -p android --bundle
- 把生成的
index.android.bundle放到Library模块的src/main/assets目录,把图片等资源复制到对应的res/drawable、res/mipmap等目录。
3. 封装原生ViewWrapper
在Library模块里写一个原生View类,封装ReactRootView,让宿主app可以像用普通原生View一样引用你的RN组件:
// rn-widget-library/src/main/java/com/yourcompany/rnwidgetlibrary/RNWidgetView.java package com.yourcompany.rnwidgetlibrary; import android.app.Activity; import android.content.Context; import android.app.Application; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactRootView; import com.facebook.react.common.LifecycleState; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.shell.MainReactPackage; import com.horcrux.svg.SvgPackage; // react-native-svg的原生Package public class RNWidgetView extends ReactRootView implements DefaultHardwareBackBtnHandler { private ReactInstanceManager mReactInstanceManager; public RNWidgetView(Context context) { super(context); // 初始化RN实例管理器 mReactInstanceManager = ReactInstanceManager.builder() .setApplication((Application) context.getApplicationContext()) .setCurrentActivity((Activity) context) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackage(new MainReactPackage()) .addPackage(new SvgPackage()) // 注册第三方库的Package .setUseDeveloperSupport(false) // 生产环境关闭开发者支持 .setInitialLifecycleState(LifecycleState.RESUMED) .build(); // 启动你的RN组件,这里的名称要和RN端注册的一致 startReactApplication(mReactInstanceManager, "HelloWorldWidget", null); } @Override public void invokeDefaultOnBackPressed() { // 处理返回键逻辑,按需实现 } }
4. 打包AAR
在Android Studio里,选中rn-widget-library模块,点击顶部菜单栏的Build > Make Module 'rn-widget-library',生成的AAR会在rn-widget-library/build/outputs/aar/目录下。
5. 宿主app集成
把AAR复制到宿主app的libs目录,然后在宿主app的build.gradle里添加引用:
// 宿主app build.gradle dependencies { implementation files('libs/rn-widget-library-release.aar') } // 记得添加RN的maven仓库,不然依赖会拉取失败 repositories { mavenCentral() maven { url 'https://maven.google.com' } maven { url "$rootDir/../node_modules/react-native/android" } maven { url "$rootDir/../node_modules/jsc-android/dist" } }
之后就可以在宿主app的布局里直接使用RNWidgetView了,或者在代码里动态初始化。
三、iOS端:打包成Framework的思路
iOS端的逻辑和Android类似:
- 用
npx expo prebuild -p ios生成原生iOS项目 - 新建一个Cocoa Touch Framework模块,把Expo生成的JS Bundle和资源导入
- 封装一个
UIView子类,初始化RCTRootView并注册你的HelloWorldWidget组件 - 用CocoaPods管理依赖,在Framework的podspec里声明RN核心、react-native-svg等依赖,确保宿主app集成时能自动获取
四、常见坑点排查
- 依赖解析失败:检查Library模块的
build.gradle是否开启了transitive = true,以及宿主app是否添加了RN的maven仓库 - react-native-svg不生效:确保在原生端正确注册了
SvgPackage(Android)或RCTSVGModule(iOS),并且打包时把第三方库的原生代码包含到了AAR/Framework里 - Expo资源不显示:一定要用
npx expo export命令生成资源,不要手动复制,因为Expo会对资源做特殊处理
内容来源于stack exchange




