react native之iOS热更新踩坑之旅

804 阅读2分钟

react native之iOS热更新踩坑之旅

为什么要有热更新?1,线上紧急bug,可以很及时修复(iOS审核一向蛋疼)。2,新功能够快速上线。3,服务端api向后不兼容的时候,不用等待审核,快速更新。ps: 目前热更新原理就是替换jsbundle,所以更改原生相关的还是需要上架审核的。这就开启了踩坑之旅,参考了不少资料,react native 更新具有天然优势,直接替换jsbundle即可。查看源代码

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
  
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

可知,在release模式下,jsbundle就是mainBundle下的main.jsbundle,然后我就憨憨的在本地启了一个node服务,提供jsbundle下载。开心开心的在跑起来,期待奇迹的发生,现实的却一直报错“error domain=nscocoaerrordomain code=513”,原因是“Specifically, you cannot modify the contents of a compiled app's bundle folder. This is because the bundle is the compiled application. When you eventually distribute the app through the iTunes App Store, the application has a digital signature that validates the contents of the app. This signature is generated at compile time. If you try to change the bundle after compilation, the app changes and the digital signature is no longer valid. This invalidates the application — who knows what code is in there, right? — and end users won't be able to run it. So Apple has set up iOS to throw an error if you try to modify the bundle. Instead of writing to the bundle, your app can write to one of three accepted app-specific folders: Documents, Temp and Cache. Most likely, you will want to write to the Documents folder.” 大致意思苹果爸爸为了安全的原因,mainBundle这里我们这些写开发者是不能动滴。不敢挑战苹果爸爸的权威,既然不能动mainBundle,只能动苹果爸爸为我们准备的Temp、Cache、Documents三者,根据含义我挑选了Documents。然后改动如下。

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  if([self hotJsbundleIsExist]) {
    return [NSURL fileURLWithPath:[self hotJsbundlePath]];
  }
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

- (BOOL)hotJsbundleIsExist {
  NSFileManager *fileManager = [NSFileManager defaultManager];
  return [fileManager fileExistsAtPath: [self hotJsbundlePath]];
}

- (NSString *)hotJsbundlePath {
  NSString *director = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
  NSString *fileName = @"main.jsbundle";
  NSString *filePath = [director stringByAppendingPathComponent:fileName];
  return  filePath;
}

最后激动搓着小手的,又一次运行跑起代码。哈哈哈。。。,这次终于可以了。咦!感觉哪里不对,我屮艸芔茻,本地图片没有显示。我想静静。。。,静态资源相对路径不对了,这就难为我了。经过一段时间思考,既然静态资源路径不对了,那就在下载jsbundle,把静态资源assets随jsbundle一同下载(ps: 不是瞎搞,是有根据的,根据jsbundle打包命令,两者是同一文件下的)。try try。。。,可爱的图片终于出现了。

react-native bundle --entry-file ./index.js --bundle-output ./ios/bundle/index.ios.jsbundle --platform ios --assets-dest ./ios/bundle --dev false