JSPatch 是 iOS 平臺上的一個(gè)開源庫,只需接入極小的三個(gè)引擎文件,即可以用 JS 調(diào)用和替換任意 OC 方法,也就是說可以在 APP 上線后通過下發(fā) JS 腳本,實(shí)時(shí)修改任意 OC 方法的實(shí)現(xiàn),達(dá)到修復(fù) bug 或動態(tài)運(yùn)營的目的。目前 JSPatch 被大規(guī)模應(yīng)用于熱修復(fù)(hotfix),已有超過 2500 個(gè) APP 接入。
雖然 JSPatch 目前大部分只用于熱修復(fù),但因?yàn)?JSPatch 可以調(diào)用任意 OC 方法,實(shí)際上它也可以做熱更新的工作,也就是動態(tài)為 APP 添加功能模塊,并對這些功能模塊進(jìn)行實(shí)時(shí)更新,可以起到跟 React Native 一樣的作用。我們從學(xué)習(xí)成本、接入成本、開發(fā)效率、熱更新能力和性能體驗(yàn)這幾個(gè)方面來對比一下使用 React Native 和 JSPatch 做熱更新的差異。
學(xué)習(xí)成本
React Native 是從 web 前端開發(fā)框架 React 延伸出來的解決方案,主要解決的問題是web頁面在移動端性能低的問題,React Native 讓開發(fā)者可以像開發(fā)web頁面那樣用 React 的方式開發(fā)功能,同時(shí)框架會通過 JS 與 OC 的通信讓界面使用原生組件渲染,讓開發(fā)出來的功能擁有原生APP的性能和體驗(yàn)。
這里會有一個(gè)學(xué)習(xí)成本的問題,大部分 iOS 開發(fā)者并不熟悉web前端開發(fā),當(dāng)他們需要一個(gè)動態(tài)化的方案去開發(fā)一個(gè)功能模塊時(shí),若使用React Native,就意味著他需要學(xué)習(xí)web前端的一整套開發(fā)技能,學(xué)習(xí)成本很高,所以目前一些使用 React Native 的團(tuán)隊(duì)里,這部分功能的開發(fā)是由前端開發(fā)者負(fù)責(zé),而不是終端開發(fā)者負(fù)責(zé)。
但前端開發(fā)者負(fù)責(zé)這部分功能也會有一些學(xué)習(xí)成本的問題,因?yàn)?React Native 還未達(dá)到十分成熟的程度,出了bug或有性能問題需要深入 React Native 客戶端代碼去排查和優(yōu)化。也就是說 React-Native 是跨 web 前端開發(fā)和終端開發(fā)的技術(shù),要求使用者同時(shí)有這兩方面能力才能使用得當(dāng),這不可避免帶來學(xué)習(xí)成本的提高。
而 JSPatch 是從終端開發(fā)出發(fā)的一種方案,JSPatch 寫出來的代碼風(fēng)格與 OC 原生開發(fā)一致,使用者不需要有 web 前端的知識和經(jīng)驗(yàn),只需要有 iOS 開發(fā)經(jīng)驗(yàn),再加上一點(diǎn) JS 語法的了解,就可以很好地使用,對終端開發(fā)來說學(xué)習(xí)成本很低。
可以看一下同樣實(shí)現(xiàn)一個(gè)簡單的界面,React Native 和 JSPatch 代碼的對比:
接入成本
接入成本上,React Native 是比較大的框架,據(jù)統(tǒng)計(jì)目前核心代碼里 OC 和 JS 代碼加起來有4w行,接入后安裝包體積增大 1.8M 左右。而 JSPatch 是微型框架,只有 3 個(gè)文件 2k 行代碼,接入后增大 100K 左右。另外 React Native 需要搭建一套開發(fā)環(huán)境,有很多依賴的庫,環(huán)境的搭建被稱為一個(gè)痛點(diǎn)。而 JSPatch 無需搭建環(huán)境,只需要拖入三個(gè)文件到工程中即可使用。
React Native 是大框架,維護(hù)起來成本也會增大,在性能調(diào)優(yōu)和 bug 查找時(shí),必須深入了解整個(gè)框架的原理和執(zhí)行流程,此外 React Native 目前還未達(dá)到穩(wěn)定狀態(tài),升級時(shí)踩坑不可避免。相對來說 JSPatch 接入后的維護(hù)成本會低一些,因?yàn)?JSPatch 只是作為很薄的一層轉(zhuǎn)接口,沒有太多規(guī)則和框架,也就沒有太多坑,本身代碼量小,需要深入了解去調(diào)試 bug 或性能調(diào)優(yōu)時(shí)成本也低。
開發(fā)效率
在 UI 層上目前 HTML + CSS 的方式開發(fā)效率是比手寫布局高的,React Native 也是用近似 HTML+CSS 去繪制 UI,這方面開發(fā)效率相對 JSPatch 會高一些,但 JSPatch 也可以借助 iOS 一些成熟的庫去提高效率,例如使用 Massory,讓 UI 的開發(fā)效率不會相差太多。邏輯層方面的開發(fā)效率雙方是一樣的。
此外 React Native 在開發(fā)效率上的另一個(gè)優(yōu)勢是支持跨平臺,React Native 本意是復(fù)用邏輯層代碼,UI 層根據(jù)不同平臺寫不同的代碼,但 UI 層目前也可以通過 ReactMix 之類的工具做到跨平臺,所以UI層和邏輯層代碼都能得到一定程度的復(fù)用。而 JSPatch 目前只能用于 iOS 平臺,沒有跨平臺能力。
實(shí)際上跨平臺有它適用和不適用的場景,跨平臺有它的代價(jià),就是需要兼顧每個(gè)平臺的特性,導(dǎo)致效果不佳。
跨平臺典型的適用場景是電商活動頁面,以展示為主,重開發(fā)效率輕交互體驗(yàn),但不適用于功能性的模塊。對 Android 來說目前熱更新方案十分成熟,Android 十分自由,可以直接用原生開發(fā)后生成diff包下發(fā)運(yùn)行,這種無論是開發(fā)效率和效果都是最好的。所以若是重體驗(yàn)的功能模塊,Android使用原生的熱更新方案,iOS 使用 JSPatch 開發(fā),會更適合。
JSPatch 也做了一些事情嘗試提高開發(fā)效率,例如做了 XCode 代碼提示插件 JSPatchX,讓用 JS 調(diào)用 OC 代碼時(shí)會出現(xiàn)代碼提示,另外跟 React Native 一樣有開發(fā)時(shí)可以實(shí)時(shí)刷新界面查看修改效果的功能,目前仍在繼續(xù)做一些措施和工具提高開發(fā)效率。
熱更新能力
React Native 和 JSPatch 都能對用其開發(fā)出來的功能模塊進(jìn)行熱更新,這也是這種方案最大的好處。不過 React Native 在熱更新時(shí)無法使用事先沒有做過橋接的原生組件,例如需要加一個(gè)發(fā)送短信功能,需要用到原生 MessageUI.framework 的接口,若沒有在編譯時(shí)加上提供給 JS 的接口,是無法調(diào)用到的。而 JSPatch 可以調(diào)用到任意已在項(xiàng)目里的組件,以及任意原生 framework 接口,不需要事先做橋接,在熱更新的能力上,相對來說 JSPatch 的能力和自由度會更高一些。
性能體驗(yàn)
使用 React Native 和 JSPatch 性能上會比原生差點(diǎn),但都能得到比純 H5 頁面或 hybrid 更好的性能和體驗(yàn)。
JSPatch 的性能問題主要在于 JS 和 OC 的通信,每次調(diào)用 OC 方法都要通過 OC runtime 接口,并進(jìn)行參數(shù)轉(zhuǎn)換。runtime 接口調(diào)用帶來的耗時(shí)一般不會成為瓶頸,參數(shù)轉(zhuǎn)換則需要注意避免在 JS 和 OC 之間傳遞大的數(shù)據(jù)集合對象。JSPatch 在性能方面也針對開發(fā)功能做了不少優(yōu)化,盡力減少了 JS 和 OC 的通信,github 項(xiàng)目主頁上有完整的小 App demo,目前來看并沒有碰到太多性能問題。
React Native 的性能問題會復(fù)雜一些,因?yàn)榭蚣鼙旧淼哪K初始化/react組件初始化/JS渲染邏輯等會消耗不少時(shí)間和內(nèi)存,這些地方若使用或優(yōu)化不當(dāng)都會對性能和體驗(yàn)造成影響。JS 和 OC 的通信也是一個(gè)耗性能的點(diǎn),不過這點(diǎn)上 React Native 優(yōu)化得比較好,沒有成為主要消耗點(diǎn)。
在性能和體驗(yàn)問題上,兩者有不同的性能消耗點(diǎn),從最終效果來看兩者差別不大。
總結(jié)
總的來說,JSPatch在學(xué)習(xí)成本,接入成本,熱更新能力上占優(yōu),而 React Native 在開發(fā)效率和跨平臺能力上占優(yōu),大家可以根據(jù)需求的不同選用不同的熱更新方案。JSPatch 目前仍在不斷發(fā)展中,后續(xù)會致力于提高開發(fā)效率,完善周邊支持,歡迎參與這個(gè)開源項(xiàng)目的開發(fā)。