codepush實(shí)現(xiàn)原理
code-push.png
梳理下關(guān)鍵節(jié)點(diǎn)
- 前端獲取serverURL、appVersion挤茄、deploymentKey
- 請(qǐng)求serverURL查詢deploymentKey對(duì)應(yīng)的包是否需要更新如叼,appVersion作為匹配條件(后續(xù)灰度發(fā)布可自行增加其他條件)
- 服務(wù)端返回downloadUrl、packageHash(一組唯一迭代hash值驮樊,類似versionCode或者build號(hào))
- 請(qǐng)求downloadUrl下載最新bundle包薇正,通過packageHash作為路徑標(biāo)識(shí)存放到本地
- 加載bundle的時(shí)候檢查是否存在更新包,獲取緩存的packageHash并加載bundle包
- 如最新bundle包出現(xiàn)異常囚衔,自動(dòng)回滾到上一版...
原生與RN混合開發(fā)codepush存在的問題
- deploymentKey作為靜態(tài)變量保存挖腰,如果切換到別的頁(yè)面,為了獲取正確的bundle資源练湿,需要再次設(shè)置對(duì)應(yīng)資源的deploymentKey猴仑,原先的deploymentKey將會(huì)被覆蓋,那么原先加載完成的數(shù)據(jù)將會(huì)面對(duì)資源不一致的問題肥哎,無法正確更新辽俗;
- codepush下載事務(wù)機(jī)制是每次只下載一個(gè)任務(wù),如該任務(wù)已經(jīng)存在篡诽,將不會(huì)繼續(xù)檢查更新下載崖飘;然而,混合開發(fā)的情況下杈女,前一個(gè)下載任務(wù)正在執(zhí)行朱浴,如果切換到別的頁(yè)面吊圾,加載另一個(gè)不相關(guān)的bundle,也不會(huì)進(jìn)行數(shù)據(jù)更新檢查翰蠢,將會(huì)浪費(fèi)更新機(jī)會(huì)项乒;
重構(gòu)方案
基于以上存在的問題,要對(duì)現(xiàn)有的codepush結(jié)構(gòu)進(jìn)行調(diào)整梁沧,首先就是要支持多個(gè)不同bundle同時(shí)更新檀何,需要業(yè)務(wù)層自行傳入關(guān)鍵字來區(qū)分需要更新哪個(gè)bundle;再者對(duì)codepush更新后的bundle存放路徑需要進(jìn)行關(guān)鍵字分組廷支,方便按組清理和回滾频鉴;
- js端對(duì)現(xiàn)有結(jié)構(gòu)改造,傳入bundle名酥泞,調(diào)用方法:
CodePush({ bundle: "bundleName" });
- deploymentKey和bundleName做一組映射砚殿,js向原生傳遞bundleName啃憎,原生自行轉(zhuǎn)換成deploymentKey芝囤,映射由外部轉(zhuǎn)換完傳入,然后將deploymentKey回傳給js進(jìn)行更新檢查辛萍,改造方法(android雷同):
//由業(yè)務(wù)測(cè)根據(jù)配置項(xiàng)返回deploymentKey
- (NSString *)getDeploymentKey:(NSString *)bundleName;
- 改造更新完的bundle存放路徑規(guī)則悯姊,將原有路徑: ./CodePush/{packageHash}/{file}添加一個(gè)deploymentKey分組,改為:./CodePush/{deploymentKey}/{packageHash}/{file}贩毕,如需要清理或回滾悯许,可通過deploymentKey關(guān)鍵字查找路徑,全部清理或回滾到上一版packageHash包體(android雷同)
+ (NSString *)getPackageFolderPath:(NSString *)deploymentKey packageHash:(NSString *)packageHash
{
return [[self getDeploymentFilePath:deploymentKey] stringByAppendingPathComponent:packageHash];
}
+ (NSString *)getDeploymentFilePath:(NSString *)deploymentKey
{
return [[self getCodePushPath] stringByAppendingPathComponent:deploymentKey];;
}
當(dāng)然辉阶,codepush重構(gòu)的改造量還是比較多的先壕,這些屬于冰山一角,獲取deploymentKey幾乎貫穿整個(gè)事務(wù)谆甜;js初始的時(shí)候只傳入bundleName垃僚,同名bundleName在不同的工程項(xiàng)目中配置的deploymentKey是不同的,需要原生業(yè)務(wù)代碼提供规辱;不同deploymentKey也需要獨(dú)立緩存最新包信息谆棺,便于更新后獲取并加載等等;
feature
- codepush私有服務(wù)改造
- 白名單發(fā)布罕袋、灰度發(fā)布(設(shè)置多種更新條件)
- 更新后監(jiān)控?cái)?shù)據(jù)回傳