先声明:我这个不是codepush那种的热更新,只是我记录实现我需求中的一些问题。
- 我的情况是,我的RN js代码在服务器,而我的iOS和Android native代码在我的本地。测试的时候,需要把RN打包作为本地包放到项目中
- iOS
一般情况RN的URL应该是localhost,使用的时候在本地npm start
启动服务器,我这里指向的是服务器的地址
// NSURL *jsUrl = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
// NSURL *jsUrl = [NSURL URLWithString:@"http://ip"];
bridge = [[RCTBridge alloc] initWithBundleURL:jsUrl moduleProvider:nil launchOptions:launchOptions];
在需要使用RN view的页面传入bridge
生成RN页面
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.reactView = [[RCTRootView alloc]
initWithBridge:delegate.bridge
moduleName:@"name"
initialProperties:@{
@"page" : @"main",
@"NativeRN":@(1),
}
];
[self.view addSubview:self.reactView];
现在需要打包出来bundle,然后放入项目中。打包的时候注意两点,Android打包同理:详细参考
- 入口文件,我这里index.js 你的可能是index.ios.js.
- bundle目录要提前创建好
react-native bundle --entry-file index.js --bundle-output ./ios/bundle/index.ios.jsbundle --platform ios --assets-dest ./ios/bundle --dev false
打包成功以后iOS的文件有这些
Android打包以后
把bundle文件,从服务器上下载到本地。
- iOS把
index.ios.jsbundle
和图片资源文件夹assets
分别copy进项目就可以了,IOS需要注意的就是导入assets目录的时候要选择 create folder ,否则看不见图片
加载RN的代码改一下,改成使用本地的bundle
NSURL *jsUrl = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"index.ios.jsbundle" ofType:nil]];;
bridge = [[RCTBridge alloc] initWithBundleURL:jsUrl moduleProvider:nil launchOptions:launchOptions];
- Android Android正常把bundle copy到项目以后,改一下加载RN的代码就可以了。我这里的代码改的是
setBundleAssetName("index.android.bundle")
里面的包名,改成index.android.jsbundle
其实Android我遇到的问题还是比较多的,这里的修改与Android的加载RN的方式有关系,代码里加载的是项目里面的bundle,所以这里写成builder.setBundleAssetName(Assertions.assertNotNull("index.android.jsbundle")); 还有一种方式就是文件里面加载RN,那样就需要修改getJSBundleFile()方法
可以参考这里,了解RN的加载机制
ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
.setApplication(getApplication())
.setCurrentActivity(this)
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index")
//.addPackage(new CodePush(CoinexConstant.codepush_key_production, getApplicationContext(), BuildConfig.DEBUG))
// .setJSBundleFile(CodePush.getJSBundleFile())
.addPackage(new MainReactPackage())
.addPackage(new NotificationPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED);
// builder.setBundleAssetName(Assertions.assertNotNull("index.android.jsbundle"));
mReactInstanceManager = builder.build();
String jsonString = "{\"scores\":[{\"name\":\"A\",\"value\":1},{\"name\":\"B\",\"value\":2}]}";
jsonString = "{\"page\":\"login\",\"NativeRN\":1}";
Bundle initialProps = JsonUtils.jsonStringToBundle(jsonString);
mReactRootView = new ReactRootView(this);
mReactRootView.startReactApplication(mReactInstanceManager, CoinexConstant.moduleName, initialProps);
setContentView(mReactRootView);