react native ios版本热更新

react native 热更新的好处

js脚本代码改变了,比如对ui进行了一些修改,客户端要是想更新的话,如果直接下载apk 或者ipa,一个是浪费流量,还有比较麻烦

热更新只要下载打包好的bundle 文件,然后进行替换就可以了

思路比较简单,客户端跟服务端都维持 一个bundle版本信息,如果服务端的版本比客户端的 版本新就下载,然后替换掉 重新渲染就OK了

具体实现,如果没有 热更新,载入bundle的代码是这样的

jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];

如果加入热更新,是这样的

NSURL *jsCodeLocation=nil;

  jsCodeLocation=[self getBundle];

  if(jsCodeLocation==nil)
  {
    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
  }
getBundle 函数就包含加载 服务端获取到的bundle 的逻辑
-(NSURL *) getBundle
{
  NSString* ss=@"#####";//服务端bundle版本号的地址
  NSString* str = [self httpGet:ss];
  NSString *pathDocuments=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

  NSString *createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,@"version.txt"];//用文件名补全路径
  Boolean bb=false;
  NSFileManager *defaultManager;
  defaultManager = [NSFileManager defaultManager];
  NSURL *nsurl=nil;
  if ([[NSFileManager defaultManager] fileExistsAtPath:createPath])//判断文件是否已存在
  {
     NSString* fileContents = [NSString stringWithContentsOfFile:createPath encoding:NSUTF8StringEncoding error:nil];
    int a=[str intValue];//服务端bundle版本号
    int b=[fileContents intValue];//客户端bundle版本信息
    if(a>b)//如果服务端的bundle版本比加大,就删除客户端的bundle,然后更新成服务端的
    {
      if ([[NSFileManager defaultManager] fileExistsAtPath:createPath])//判断文件是否已存在
      {
        [defaultManager removeItemAtPath:createPath error:NULL];
      }
      [self storeFile:@"version.txt" content:str];
      bb=true;
    }
    else//如果发现下载的bundle文件不存在,也要下载更新
    {
      createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,@"main.jsbundle"];
      if (![[NSFileManager defaultManager] fileExistsAtPath:createPath])//判断文件是否已存在
      {
        bb=true;
      }
    }
  }
  else//如果客户端的bundle是空,也要下载
  {
   [self storeFile:@"version.txt" content:str];
    bb=true;
  }
  if (bb==true) {
    createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,@"main.jsbundle"];
   if ([[NSFileManager defaultManager] fileExistsAtPath:createPath])//判断文件是否已存在
    {
      [defaultManager removeItemAtPath:createPath error:NULL];
    }
    ss=@"####";//服务端bundle文件的地址
    str = [self httpGet:ss];

    NSString *fileName=[self storeFile:@"main.jsbundle" content:str];
    nsurl=[NSURL fileURLWithPath:fileName];//这是bundle 文件的路径

  }
  else{
    createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,@"main.jsbundle"];
    nsurl=[NSURL fileURLWithPath:createPath];//这是bundle 文件的路径
  }
  return nsurl;

}
-(NSString *) httpGet:(NSString *)ss
{
  //第一步,创建URL
  NSURL *url = [NSURL URLWithString:ss];

  //第二步,通过URL创建网络请求
  NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
  //NSURLRequest初始化方法第一个参数:请求访问路径,第二个参数:缓存协议,第三个参数:网络请求超时时间(秒)
  /*其中缓存协议是个枚举类型包含:
   NSURLRequestUseProtocolCachePolicy(基础策略)
   NSURLRequestReloadIgnoringLocalCacheData(忽略本地缓存)
   NSURLRequestReturnCacheDataElseLoad(首先使用缓存,如果没有本地缓存,才从原地址下载)
   NSURLRequestReturnCacheDataDontLoad(使用本地缓存,从不下载,如果本地没有缓存,则请求失败,此策略多用于离线操作)
   NSURLRequestReloadIgnoringLocalAndRemoteCacheData(无视任何缓存策略,无论是本地的还是远程的,总是从原地址重新下载)
   NSURLRequestReloadRevalidatingCacheData(如果本地缓存是有效的则不下载,其他任何情况都从原地址重新下载)*/
  //第三步,连接服务器
  NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

  NSString *str = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding];
  return str;
}
//存储文件
-(NSString *)storeFile:(NSString *)fileName content:(NSString *)writeContent
{
  NSString *pathDocuments=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

  NSString *createPath=[NSString stringWithFormat:@"%@/%@",pathDocuments,fileName];//用文件名补全路径
  NSError *ReadFileError;
  NSString *readContent ;
  NSData *data ;
  if ([[NSFileManager defaultManager] fileExistsAtPath:createPath])//判断文件是否已存在
  {
    if (nil == writeContent) {
      readContent = [NSString stringWithContentsOfFile:createPath encoding:NSUTF8StringEncoding error:&ReadFileError];
    }else{
      data = [writeContent dataUsingEncoding:NSUTF8StringEncoding];//新文件的初始数据
      [[NSFileManager defaultManager] createFileAtPath:createPath contents:data attributes:nil];//创建文件
      readContent = [NSString stringWithContentsOfFile:createPath encoding:NSUTF8StringEncoding error:&ReadFileError];
    }
  }
  else
  {
    if (nil == writeContent) {
      return nil;
    }else{
      data = [writeContent dataUsingEncoding:NSUTF8StringEncoding];//新文件的初始数据
      [[NSFileManager defaultManager] createFileAtPath:createPath contents:data attributes:nil];//创建文件
      readContent = [NSString stringWithContentsOfFile:createPath encoding:NSUTF8StringEncoding error:&ReadFileError];
    }
  }
  return createPath;
}

以上就是主要代码,有注释说明意思

ios bundle打包脚本如下

react-native bundle --entry-file index.ios.js --bundle-output ./bundle/index.ios.bundle --platform ios --assets-dest ./bundle --dev false
 
时间: 2024-11-10 03:01:20

react native ios版本热更新的相关文章

React Native iOS原生模块开发实战|教程|心得|如何创建React Native iOS原生模块

尊重版权,未经授权不得转载 本文出自:贾鹏辉的技术博客(http://blog.csdn.net/fengyuzhengfan/article/details/54691432) 前言 一直想写一下我在React Native原生模块封装方面的一些经验和心得,来分享给大家,但实在抽不开身,今天看了一下日历发现马上就春节了,所以就赶在春节之前将这篇博文写好并发布(其实是两篇:要看Android篇的点这里<React Native Android原生模块开发>). 我平时在用React Nativ

React Native IOS ---基础环境搭建(前端架构师)

React Native -IOS 开发环境搭建 web架构(基础) 安装依赖 * 必须安装的依赖有:Node.Watchman 和 React Native 命令行工具以及 Xcode. npm 镜像 npm config set registry https://registry.npm.taobao.org --global npm config set disturl https://npm.taobao.org/dist --global Yarn.React Native 的命令行工

React Native iOS环境搭建

前段时间React Native for Android发布,感觉React Native会越来越多的公司开始研究.使用.所以周六也抽空搭建了iOS的开发环境,以便以后利用空闲的时间能够学习一下. 废话不多说了,下面简单的列出步骤吧. 1. 安装Homebrew Homebrew主要用于安装后面需要安装的watchman.flow 打开MAC的终端,输入如下命令: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/i

编译依赖于React Native0.46.4的React Native IOS工程时,出现错误“fatal error: &#39;React/RCTEventEmitter.h&#39; file not found”

我的环境: WebStorm 2017.2Build #WS-172.3317.70, built on July 14, 2017 JRE: 1.8.0_152-release-915-b5 x86_64JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o Mac OS X 10.12.6 Xcode8.3.3(8E3004b) 网上搜索,可以解决我的问题的网址:https://stackoverflow.com/questions/41663002

ios WaxPatch热更新原理

以下是引用他人文章内容: 为什么需要 WaxPatch 很多情况下,已经在 AppStore 上线的应用需要紧急缺陷修复,此时便需要使用某些技术手段,使应用程序能够动态下载补丁,进行缺陷修复. 什么是 WaxPatch 迄今为止,脚本语言中运行速度最快的是 Lua.Lua 语言由巴西里约热内卢天主教大学的 Roberto Ierusalimschy.Waldemar Celes 和 Luiz Henrique de Figueiredo 于 1993 年开发的.其最初的设计目的是提供一个方便嵌入

React Native for Android 热部署图片自己定义方案

情景 热部署时,我们期望升级包中包括js代码与图片资源. bundle的热部署网上已经有两种方案了,一种是用反射,一种是利用RN自带函数.将bundle初始化时直接放到指定文件夹下,之后通过替换bundle文件实现代码热部署. 我们希望图片也能够实现热部署,以下是一个比較简单的解决方式. 详细需求:client解析从server下发的压缩包(zip),当中含js源文件index.android.bundle 和 图片包,解压后ReactNative指向 解压后index.android.bund

如何将IOS版本的更新下载文件指向到自己的服务器

针对那些使用企业签名但是没有发布到AppSotre的IOS版本APP自动更新问题解决方案: 在apicloud中是这样说明的: 因为要填写plist地址所以不能向安卓那样直接填写服务器文件地址,但是直接填写apicloud中的包又没有签名,所以我们用以下方式解决: 首先我们找到编译记录中的地址 例如:itms-services://?action=download-manifest&url=https://downloadpkg.apicloud.com:443/zip/ff/b2/XXXXX.

React Native IOS源码初探

原文链接 http://www.open-open.com/lib/view/open1465637638193.html 每个项目都有一个入口,然后进行初始化操作,React Native 也不例外.一个不含 Objective-C 代码的项目留给我们的唯一线索就是位于 AppDelegate 文件中的代码: RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"re

iOS 版本自动更新

AppDelegate.h - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    [self  editionUpdate]; } //版本自动更新 -(void)editionUpdate{    NSString * [email protected]"192.168.......";//获取后台的接口