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