JSPatch 是 iOS 平臺上的一個(gè)開源庫公般,只需接入極小的三個(gè)引擎文件抵卫,即可以用 JavaScript 調(diào)用和替換任意 Objective-C 方法横蜒,也就是說可以在 App 上線后通過下發(fā) JavaScript 腳本,實(shí)時(shí)修改任意 Objective-C 方法的實(shí)現(xiàn),達(dá)到修復(fù) Bug 或動(dòng)態(tài)運(yùn)營的目的蛮放。目前 JSPatch 被大規(guī)模應(yīng)用于熱修復(fù)(Hotfix),已有超過 2500 個(gè) App 接入辛燥。
雖然 JSPatch 目前大部分只用于熱修復(fù)筛武,但因?yàn)槠淇梢哉{(diào)用任意 Objective-C 方法,實(shí)際上它也可以做熱更新的工作挎塌,也就是動(dòng)態(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 頁面在移動(dòng)端性能低的問題拴驮,React Native 讓開發(fā)者可以像開發(fā) Web 頁面那樣用 React 的方式開發(fā)功能春瞬,同時(shí)框架會(huì)通過 JavaScript 與 Objective-C 的通信讓界面使用原生組件渲染,讓開發(fā)出來的功能擁有原生APP的性能和體驗(yàn)套啤。
這里會(huì)有一個(gè)學(xué)習(xí)成本的問題宽气,大部分 iOS 開發(fā)者并不熟悉 Web 前端開發(fā),當(dāng)他們需要一個(gè)動(dòng)態(tài)化的方案去開發(fā)一個(gè)功能模塊時(shí),若使用 React Native萄涯,就意味著他需要學(xué)習(xí) Web 前端的一整套開發(fā)技能绪氛,學(xué)習(xí)成本很高。所以目前一些使用 React Native 的團(tuán)隊(duì)里涝影,這部分功能的開發(fā)是由前端開發(fā)者負(fù)責(zé)枣察,而非終端開發(fā)者。
但前端開發(fā)者負(fù)責(zé)這部分功能也會(huì)有一些學(xué)習(xí)成本的問題燃逻,因?yàn)?React Native 還未十分成熟序目,出了 Bug 或有性能問題需要深入 React Native 客戶端代碼去排查和優(yōu)化。也就是說 React Native 是跨 Web 前端開發(fā)和終端開發(fā)的技術(shù)唆樊,要求使用者同時(shí)有這兩方面能力才能使用得當(dāng)宛琅,這不可避免地帶來學(xué)習(xí)成本的提高。
而 JSPatch 是從終端開發(fā)出發(fā)的一種方案逗旁,JSPatch 寫出來的代碼風(fēng)格與 Objective-C 原生開發(fā)一致,使用者不需要有 Web 前端的知識和經(jīng)驗(yàn)舆瘪,只需要有 iOS 開發(fā)經(jīng)驗(yàn)片效,再加上一點(diǎn) JavaScript 語法的了解,就可以很好地使用英古,對終端開發(fā)來說學(xué)習(xí)成本很低淀衣。
可以看一下同樣實(shí)現(xiàn)一個(gè)簡單的界面,React Native 和 JSPatch 代碼的對比:
//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 代碼加起來有 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ù)起來成本也會(huì)增大藐石,在性能調(diào)優(yōu)和 Bug 查找時(shí),必須深入了解整個(gè)框架的原理和執(zhí)行流程定拟,此外 React Native 目前還未達(dá)到穩(wěn)定狀態(tài)于微,升級時(shí)踩坑不可避免。相對來說 JSPatch 接入后的維護(hù)成本會(huì)低一些,因?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 會(huì)高一些祈远,但 JSPatch 也可以借助 iOS 一些成熟的庫去提高效率,例如使用 Masonry商源,讓 UI 的開發(fā)效率不會(huì)相差太多车份。邏輯層方面的開發(fā)效率雙方是一樣的。
此外牡彻,React Native 在開發(fā)效率上的另一個(gè)優(yōu)勢是支持跨平臺扫沼,React Native 本意是復(fù)用邏輯層代碼,UI 層根據(jù)不同平臺寫不同的代碼庄吼,但 UI 層目前也可以通過 ReactMix 之類的工具做到跨平臺缎除,所以UI層和邏輯層代碼都能得到一定程度的復(fù)用。而 JSPatch 目前只能用于 iOS 平臺总寻,沒有跨平臺能力器罐。
實(shí)際上跨平臺有它適用和不適用的場景,跨平臺有它的代價(jià)渐行,就是需要兼顧每個(gè)平臺的特性轰坊,導(dǎo)致效果不佳。
跨平臺典型的適用場景是電商活動(dòng)頁面祟印,以展示為主肴沫,重開發(fā)效率輕交互體驗(yàn),但不適用于功能性的模塊旁理。對 Android 來說目前熱更新方案十分成熟樊零,Android 十分自由,可以直接用原生開發(fā)后生成 diff 包下發(fā)運(yùn)行孽文,這種無論是開發(fā)效率和效果都是最好的驻襟。所以若是重體驗(yàn)的功能模塊,Android 使用原生的熱更新方案芋哭,iOS 使用 JSPatch 開發(fā)沉衣,會(huì)更適合。
JSPatch 也做了一些事情嘗試提高開發(fā)效率减牺,例如做了 Xcode 代碼提示插件 JSPatchX豌习,讓用 JavaScript 調(diào)用 Objective-C 代碼時(shí)會(huì)出現(xiàn)代碼提示存谎,另外跟 React Native 一樣有開發(fā)時(shí)可以實(shí)時(shí)刷新界面查看修改效果的功能,目前仍在繼續(xù)做一些措施和工具提高開發(fā)效率肥隆。
熱更新能力
React Native 和 JSPatch 都能對用其開發(fā)出來的功能模塊進(jìn)行熱更新既荚,這也是這種方案最大的好處。不過 React Native 在熱更新時(shí)無法使用事先沒有做過橋接的原生組件栋艳,例如需要加一個(gè)發(fā)送短信功能恰聘,需要用到原生 MessageUI.framework 的接口,若沒有在編譯時(shí)加上提供給 JavaScript 的接口吸占,是無法調(diào)用到的晴叨。而 JSPatch 可以調(diào)用到任意已在項(xiàng)目里的組件,以及任意原生 framework 接口矾屯,不需要事先做橋接兼蕊,在熱更新的能力上,相對來說 JSPatch 的能力和自由度會(huì)更高一些件蚕。
性能體驗(yàn)
使用 React Native 和 JSPatch 性能上會(huì)比原生差點(diǎn)孙技,但都能得到比純 H5 頁面或 hybrid 更好的性能和體驗(yàn)。
JSPatch 的性能問題主要在于 JavaScript 和 Objective-C 的通信骤坐,每次調(diào)用 Objective-C 方法都要通過 Objective-C Runtime 接口绪杏,并進(jìn)行參數(shù)轉(zhuǎn)換。runtime 接口調(diào)用帶來的耗時(shí)一般不會(huì)成為瓶頸纽绍,參數(shù)轉(zhuǎn)換則需要注意避免在 JavaScript 和 Objective-C 之間傳遞大的數(shù)據(jù)集合對象。JSPatch 在性能方面也針對開發(fā)功能做了不少優(yōu)化势似,盡力減少了 JavaScript 和 Objective-C 的通信拌夏,GitHub 項(xiàng)目主頁上有完整的小 App Demo,目前來看并沒有碰到太多性能問題履因。
React Native 的性能問題會(huì)復(fù)雜一些障簿,因?yàn)榭蚣鼙旧淼哪K初始化/React 組件初始化/JavaScript 渲染邏輯等會(huì)消耗不少時(shí)間和內(nèi)存,這些地方若使用或優(yōu)化不當(dāng)都會(huì)對性能和體驗(yàn)造成影響栅迄。JavaScript 和 Objective-C 的通信也是一個(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)(見表 1)橱乱,大家可以根據(jù)需求的不同選用不同的熱更新方案。JSPatch 目前仍在不斷發(fā)展中粱甫,后續(xù)會(huì)致力于提高開發(fā)效率泳叠,完善周邊支持,歡迎參與這個(gè)開源項(xiàng)目的開發(fā)茶宵。