React-Native做本地服務(wù)器熱更新/熱部署(IOS)

前言

? ? ? ? 某個公司考慮使用React-Native的理由有很多,熱更新/熱部署可能是一個很大的原因。如果公司認(rèn)為熱更新/熱部署是主要原因的話,那么這應(yīng)該是一個很錯誤的決定。因為APP的質(zhì)量和具有前瞻性的規(guī)劃才是您真正需要考慮的事情,而不是熱更新的補救。當(dāng)然不可否認(rèn)的是熱更新/熱部署很符合敏捷開發(fā)這個思維.......

進(jìn)入正題

? ? ? ? 現(xiàn)在熱更新的第三方服務(wù)很多:微軟的CodePush,RN中文網(wǎng)的Pushy......國內(nèi)還是推薦使用國內(nèi)的服務(wù)吧。

? ? ? ? 既然有這么多第三方服務(wù)為何還要自己開發(fā)熱更新/熱部署功能呢?

? ? ? ? 1、安全性

? ? ? ? 2、可控性

? ? ? ? 3、實現(xiàn)簡單的業(yè)務(wù)邏輯開發(fā)起來其實很簡單

? ? ? ? 4、之前使用的微軟CodePush的服務(wù)下載時出現(xiàn)很多問題,于是決定自己開發(fā)。

開發(fā)思路


開發(fā)思路

開發(fā)步驟

1、編譯項目

ios打包編譯:CD到項目根目錄運行命令

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

安卓打包請移步到打包APK

ios打包完成后在項目中的ios目錄中多出了bundle文件夾,這里就是我們打包出來的RN運行文件,實際上RN運行的就是這里的.jsbundle文件。


編譯項目目錄

2、壓縮編譯文件

把bundle文件夾壓縮為ZIP包

3、把壓縮的bundle的ZIP包上傳到后端

4、更新后臺相關(guān)的配置文件,比如:RN包的版本號、更新日志、是否強制更新、是否靜默更新、是否回滾......具體有多少功能是你們的自己的事


5、下載最新的包,這里開始是寫代碼的時候了

5.1首先網(wǎng)絡(luò)請求服務(wù)的RN配置內(nèi)容

5.2對比本地RN的版本號

5.3彈出更新

5.4下載解壓最新的包

下載和解壓文件的代碼:下載使用的是AFN、解壓使用的是SSZipArchive

AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];

? ? //下載地址

? ? NSURL*mgrurl = [NSURLURLWithString:self.updateUrl];

? ? NSURLRequest*request = [NSURLRequestrequestWithURL:mgrurl];

? ? NSURLSessionDownloadTask*download = [mgrdownloadTaskWithRequest:requestprogress:^(NSProgress*_NonnulldownloadProgress) {

? ? ? //在主線程中調(diào)用

? ? ? [[NSOperationQueue mainQueue]addOperationWithBlock:^{

? ? ? ? NSLog(@"進(jìn)度%f",1.0*downloadProgress.completedUnitCount/ downloadProgress.totalUnitCount);

? ? ? ? CGFloatjsw =1.0* downloadProgress.completedUnitCount/ downloadProgress.totalUnitCount* (PW-40);

? ? ? ? self.jdView.frame=CGRectMake(0,0, jsw,5);

? ? ? ? self.jdText.text= [NSStringstringWithFormat:@"更新進(jìn)度(%.0f/100)",100.0*downloadProgress.completedUnitCount/ downloadProgress.totalUnitCount];

? ? ? ? self.suduText.text= [NSStringstringWithFormat:@"%lldkb/s",[MLRNSingtongetInterfaceBytes]/1024/1024];

? ? ? }];

? ? }destination:^NSURL*_Nonnull(NSURL*_NonnulltargetPath,NSURLResponse*_Nonnullresponse) {

? ? ? NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];

? ? ? NSLog(@"targetPath:%@",targetPath);

? ? ? NSLog(@"fullPath:%@",fullPath);

? ? ? return[NSURLfileURLWithPath:fullPath];

? ? }completionHandler:^(NSURLResponse*_Nonnullresponse,NSURL*_NullablefilePath,NSError*_Nullableerror) {

? ? ? //下載完成,解壓

? ? ? //Caches路徑

? ? ? NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];

? ? ? NSString *xxxx = [[filePath absoluteString] substringFromIndex:7];

? ? ? [SSZipArchive unzipFileAtPath: xxxx toDestination:cachesPath];

? ? ? [[NSOperationQueue mainQueue]addOperationWithBlock:^{

? ? ? ? [MBProgressHUD hideHUD];

? ? ? ? UIStoryboard*storayobard = [UIStoryboardstoryboardWithName:@"main"bundle:nil];

? ? ? ? self.view.window.rootViewController = storayobard.instantiateInitialViewController;

? ? ? }];

? ? }];

? ? [downloadresume];

下載和解壓和重啟app

5.5運行本地的RN文件

在使用調(diào)用RN的地方(一般在AppDelegate中)

修改RCTRootView初始化方法為

RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:[[RCTBridge alloc] initWithDelegate:self launchOptions:nil] moduleName:@""name"" initialProperties:nil];


修改RCTRootView初始化方法

添加代理RCTBridgeDelegate


添加代理

實現(xiàn)RCTBridgeDelegate中的sourceURLForBridge方法

- (NSURL*)sourceURLForBridge:(RCTBridge*)bridge {

? <#code#>

}

sourceURLForBridge方法

在sourceURLForBridge方法中確定您是要使用最新那個URL中的包

我這里的邏輯是

判斷沙盒是否存在.jsbundle文件 --->? 有則使用沙盒中的.jsbundle

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 沒有則使用本地打包的文件

- (NSURL*)sourceURLForBridge:(RCTBridge*)bridge{

? NSURL*jsCodeLocation;

? // 取得沙盒目錄

? NSString *localPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

? // 要檢查的文件目錄

? NSString*filePath = [localPath? stringByAppendingPathComponent:@"bundle/index.ios.jsbundle"];

? NSFileManager *fileManager = [NSFileManager defaultManager];

? if([fileManagerfileExistsAtPath:filePath]) {

? ? NSString*newUrl = [NSStringstringWithFormat:@"file://%@",filePath];

? ? jsCodeLocation = [NSURLURLWithString:newUrl];

? ? NSLog(@"文件存在");

? ? returnjsCodeLocation;

? }else{

#if DEBUG

? ? // 原來的jsCodeLocation

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

#else

? ? jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"bundle/index.ios"withExtension:@"jsbundle"];

#endif

? ? NSLog(@"文件不存在");

? ? returnjsCodeLocation;

? }

}


判斷代碼

大功告成運行項目。

到這里最基礎(chǔ)的熱更新/熱部署服務(wù)就搭建完成。如果想要更加完善還是需要花點功夫的,畢竟師傅領(lǐng)進(jìn)門修行靠個人。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容