Hotfix與iOS 動(dòng)態(tài)更新方案 JSPatch 與 React Native 的對(duì)比

JSPatch 是 iOS 平臺(tái)上的一個(gè)開(kāi)源庫(kù),只需接入極小的三個(gè)引擎文件,即可以用 JavaScript 調(diào)用和替換任意 Objective-C 方法,也就是說(shuō)可以在 App 上線后通過(guò)下發(fā) JavaScript 腳本,實(shí)時(shí)修改任意 Objective-C 方法的實(shí)現(xiàn),達(dá)到修復(fù) Bug 或動(dòng)態(tài)運(yùn)營(yíng)的目的。目前 JSPatch 被大規(guī)模應(yīng)用于熱修復(fù)(Hotfix),已有超過(guò) 2500 個(gè) App 接入。

雖然 JSPatch 目前大部分只用于熱修復(fù),但因?yàn)槠淇梢哉{(diào)用任意 Objective-C 方法,實(shí)際上它也可以做熱更新的工作,也就是動(dòng)態(tài)為 App 添加功能模塊,并對(duì)這些功能模塊進(jìn)行實(shí)時(shí)更新,可以起到跟 React Native 一樣的作用。我們從學(xué)習(xí)成本、接入成本、開(kāi)發(fā)效率、熱更新能力和性能體驗(yàn)這幾個(gè)方面來(lái)對(duì)比一下使用 React Native 和 JSPatch 做熱更新的差異。

學(xué)習(xí)成本

React Native 是從 Web 前端開(kāi)發(fā)框架 React 延伸出來(lái)的解決方案,主要解決的問(wèn)題是 Web 頁(yè)面在移動(dòng)端性能低的問(wèn)題,React Native 讓開(kāi)發(fā)者可以像開(kāi)發(fā) Web 頁(yè)面那樣用 React 的方式開(kāi)發(fā)功能,同時(shí)框架會(huì)通過(guò) JavaScript 與 Objective-C 的通信讓界面使用原生組件渲染,讓開(kāi)發(fā)出來(lái)的功能擁有原生APP的性能和體驗(yàn)。

這里會(huì)有一個(gè)學(xué)習(xí)成本的問(wèn)題,大部分 iOS 開(kāi)發(fā)者并不熟悉 Web 前端開(kāi)發(fā),當(dāng)他們需要一個(gè)動(dòng)態(tài)化的方案去開(kāi)發(fā)一個(gè)功能模塊時(shí),若使用 React Native,就意味著他需要學(xué)習(xí) Web 前端的一整套開(kāi)發(fā)技能,學(xué)習(xí)成本很高。所以目前一些使用 React Native 的團(tuán)隊(duì)里,這部分功能的開(kāi)發(fā)是由前端開(kāi)發(fā)者負(fù)責(zé),而非終端開(kāi)發(fā)者。

但前端開(kāi)發(fā)者負(fù)責(zé)這部分功能也會(huì)有一些學(xué)習(xí)成本的問(wèn)題,因?yàn)?React Native 還未十分成熟,出了 Bug 或有性能問(wèn)題需要深入 React Native 客戶端代碼去排查和優(yōu)化。也就是說(shuō) React Native 是跨 Web 前端開(kāi)發(fā)和終端開(kāi)發(fā)的技術(shù),要求使用者同時(shí)有這兩方面能力才能使用得當(dāng),這不可避免地帶來(lái)學(xué)習(xí)成本的提高。

而 JSPatch 是從終端開(kāi)發(fā)出發(fā)的一種方案,JSPatch 寫(xiě)出來(lái)的代碼風(fēng)格與 Objective-C 原生開(kāi)發(fā)一致,使用者不需要有 Web 前端的知識(shí)和經(jīng)驗(yàn),只需要有 iOS 開(kāi)發(fā)經(jīng)驗(yàn),再加上一點(diǎn) JavaScript 語(yǔ)法的了解,就可以很好地使用,對(duì)終端開(kāi)發(fā)來(lái)說(shuō)學(xué)習(xí)成本很低。

可以看一下同樣實(shí)現(xiàn)一個(gè)簡(jiǎn)單的界面,React Native 和 JSPatch 代碼的對(duì)比:

//React Native
class HelloWorld extends Component {
  render() {    
     return (      
       <View style={styles.btnArea}>
        <View style={styles.btnWrapper}>
          <TouchableHighlight underlayColor="#ED5F37” onPress={this.login}
              activeOpacity={0.7}>
            <Text style={styles.btn}>登錄</Text>
          </TouchableHighlight>
        </View>
      </View>
    );
  }
  login(){

  };
}

var styles = StyleSheet.create({
  btnArea: {
    justifyContent: 'center',
    marginLeft: 20,
    marginRight: 20,
    marginTop: 100,
    flexDirection: 'row',
  },
  btnWrapper: {
    backgroundColor: '#FC6E50',
    borderRadius: 5,
    flex: 1
  },
  btn: {
    paddingTop: 10,
    paddingBottom: 10,
    color: '#ffffff',
    textAlign: 'center',
  },
});
//JSPatch
require('UIColor, UIScreen, UIButton')
defineClass('HelloWord : UIView', {
    initWithFrame: function(frame) {        
if(self = super.initWithFrame(frame)){              
    var screenWidth = UIScreen.mainScreen().bounds().width            
    var loginBtn = UIButton.alloc().initWithFrame({x: 20, y: 50, width: screenWidth - 40, height: 30});
    loginBtn.setBackgroundColor(UIColor.greenColor())
    loginBtn.setTitle_forState("Login", 0)
    loginBtn.layer().setCornerRadius(5)
    loginBtn.addTarget_action_forControlEvents(self, 'handleBtn', 1<<6);
    self.addSubview(loginBtn);
        }       
       return self;
    },
    handleBtn: function() {
    }
})
接入成本

接入成本上,React Native 是比較大的框架,據(jù)統(tǒng)計(jì)目前核心代碼里Objective-C 和 JavaScript 代碼加起來(lái)有 4w 行,接入后安裝包體積增大 1.8M 左右。而 JSPatch 是微型框架,只有 3 個(gè)文件 2k 行代碼,接入后增大 100K 左右。另外 React Native 需要搭建一套開(kāi)發(fā)環(huán)境,有很多依賴的庫(kù),環(huán)境的搭建是一個(gè)痛點(diǎn)。而 JSPatch 無(wú)需搭建環(huán)境,只需拖入三個(gè)文件到工程中即可使用。

React Native 是大框架,維護(hù)起來(lái)成本也會(huì)增大,在性能調(diào)優(yōu)和 Bug 查找時(shí),必須深入了解整個(gè)框架的原理和執(zhí)行流程,此外 React Native 目前還未達(dá)到穩(wěn)定狀態(tài),升級(jí)時(shí)踩坑不可避免。相對(duì)來(lái)說(shuō) JSPatch 接入后的維護(hù)成本會(huì)低一些,因?yàn)?JSPatch 只是作為很薄的一層轉(zhuǎn)接口,沒(méi)有太多規(guī)則和框架,也就沒(méi)有太多坑,本身代碼量小,需要深入了解去調(diào)試 Bug 或性能調(diào)優(yōu)時(shí)成本也低。

開(kāi)發(fā)效率

在 UI 層上目前 HTML + CSS 的方式開(kāi)發(fā)效率是比手寫(xiě)布局高的,React Native 也是用近似 HTML+CSS 去繪制 UI,這方面開(kāi)發(fā)效率相對(duì) JSPatch 會(huì)高一些,但 JSPatch 也可以借助 iOS 一些成熟的庫(kù)去提高效率,例如使用 Masonry,讓 UI 的開(kāi)發(fā)效率不會(huì)相差太多。邏輯層方面的開(kāi)發(fā)效率雙方是一樣的。

此外,React Native 在開(kāi)發(fā)效率上的另一個(gè)優(yōu)勢(shì)是支持跨平臺(tái),React Native 本意是復(fù)用邏輯層代碼,UI 層根據(jù)不同平臺(tái)寫(xiě)不同的代碼,但 UI 層目前也可以通過(guò) ReactMix 之類的工具做到跨平臺(tái),所以UI層和邏輯層代碼都能得到一定程度的復(fù)用。而 JSPatch 目前只能用于 iOS 平臺(tái),沒(méi)有跨平臺(tái)能力。
實(shí)際上跨平臺(tái)有它適用和不適用的場(chǎng)景,跨平臺(tái)有它的代價(jià),就是需要兼顧每個(gè)平臺(tái)的特性,導(dǎo)致效果不佳。

跨平臺(tái)典型的適用場(chǎng)景是電商活動(dòng)頁(yè)面,以展示為主,重開(kāi)發(fā)效率輕交互體驗(yàn),但不適用于功能性的模塊。對(duì) Android 來(lái)說(shuō)目前熱更新方案十分成熟,Android 十分自由,可以直接用原生開(kāi)發(fā)后生成 diff 包下發(fā)運(yùn)行,這種無(wú)論是開(kāi)發(fā)效率和效果都是最好的。所以若是重體驗(yàn)的功能模塊,Android 使用原生的熱更新方案,iOS 使用 JSPatch 開(kāi)發(fā),會(huì)更適合。

JSPatch 也做了一些事情嘗試提高開(kāi)發(fā)效率,例如做了 Xcode 代碼提示插件 JSPatchX,讓用 JavaScript 調(diào)用 Objective-C 代碼時(shí)會(huì)出現(xiàn)代碼提示,另外跟 React Native 一樣有開(kāi)發(fā)時(shí)可以實(shí)時(shí)刷新界面查看修改效果的功能,目前仍在繼續(xù)做一些措施和工具提高開(kāi)發(fā)效率。

熱更新能力

React Native 和 JSPatch 都能對(duì)用其開(kāi)發(fā)出來(lái)的功能模塊進(jìn)行熱更新,這也是這種方案最大的好處。不過(guò) React Native 在熱更新時(shí)無(wú)法使用事先沒(méi)有做過(guò)橋接的原生組件,例如需要加一個(gè)發(fā)送短信功能,需要用到原生 MessageUI.framework 的接口,若沒(méi)有在編譯時(shí)加上提供給 JavaScript 的接口,是無(wú)法調(diào)用到的。而 JSPatch 可以調(diào)用到任意已在項(xiàng)目里的組件,以及任意原生 framework 接口,不需要事先做橋接,在熱更新的能力上,相對(duì)來(lái)說(shuō) JSPatch 的能力和自由度會(huì)更高一些。

性能體驗(yàn)

使用 React Native 和 JSPatch 性能上會(huì)比原生差點(diǎn),但都能得到比純 H5 頁(yè)面或 hybrid 更好的性能和體驗(yàn)。

JSPatch 的性能問(wèn)題主要在于 JavaScript 和 Objective-C 的通信,每次調(diào)用 Objective-C 方法都要通過(guò) Objective-C Runtime 接口,并進(jìn)行參數(shù)轉(zhuǎn)換。runtime 接口調(diào)用帶來(lái)的耗時(shí)一般不會(huì)成為瓶頸,參數(shù)轉(zhuǎn)換則需要注意避免在 JavaScript 和 Objective-C 之間傳遞大的數(shù)據(jù)集合對(duì)象。JSPatch 在性能方面也針對(duì)開(kāi)發(fā)功能做了不少優(yōu)化,盡力減少了 JavaScript 和 Objective-C 的通信,GitHub 項(xiàng)目主頁(yè)上有完整的小 App Demo,目前來(lái)看并沒(méi)有碰到太多性能問(wèn)題。

React Native 的性能問(wèn)題會(huì)復(fù)雜一些,因?yàn)榭蚣鼙旧淼哪K初始化/React 組件初始化/JavaScript 渲染邏輯等會(huì)消耗不少時(shí)間和內(nèi)存,這些地方若使用或優(yōu)化不當(dāng)都會(huì)對(duì)性能和體驗(yàn)造成影響。JavaScript 和 Objective-C 的通信也是一個(gè)耗性能的點(diǎn),不過(guò)這點(diǎn)上 React Native 優(yōu)化得比較好,沒(méi)有成為主要消耗點(diǎn)。

在性能和體驗(yàn)問(wèn)題上,兩者有不同的性能消耗點(diǎn),從最終效果來(lái)看兩者差別不大。

總結(jié)
E5FDFD5E-3CEB-4931-9A1C-0F97CABDF929.png

總的來(lái)說(shuō),JSPatch在學(xué)習(xí)成本、接入成本、熱更新能力上占優(yōu),而 React Native 在開(kāi)發(fā)效率和跨平臺(tái)能力上占優(yōu)(見(jiàn)表 1),大家可以根據(jù)需求的不同選用不同的熱更新方案。JSPatch 目前仍在不斷發(fā)展中,后續(xù)會(huì)致力于提高開(kāi)發(fā)效率,完善周邊支持,歡迎參與這個(gè)開(kāi)源項(xiàng)目的開(kāi)發(fā)。

@bang原文鏈接
擴(kuò)展JSPatch實(shí)現(xiàn)原理詳解

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

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

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