DHH 談混合移動(dòng)應(yīng)用開發(fā)
David,Ruby on Rails 作者,37signals 合伙人
暢銷書作家、演說家、賽車手、業(yè)余攝影師、顧家好男人
37signals 在2013年2月發(fā)布了 Basecamp 的 iPhone app,在此之前我們就使用原生開發(fā)(native)還是混合開發(fā)(hybrid)做了許多嘗試。在2012年項(xiàng)目啟動(dòng)的時(shí)候,大多數(shù)人都傾向于原生開發(fā)。
Facebook 在2012年發(fā)布了他們新的 iOS app,為了獲得更好的用戶體驗(yàn),他們放棄了原來的 HTML5 混合開發(fā)方式??紤]到2010~2011年的時(shí)候,HTML 在移動(dòng)端的性能確實(shí)不盡如人意,這個(gè)決定在當(dāng)時(shí)看來也在情理之中。2010年的時(shí)候我們覺得 iPhone 3G/3GS 夠眩夠快,但按照現(xiàn)在的標(biāo)準(zhǔn)來看它們就太慢了。因此在為移動(dòng)應(yīng)用開發(fā)做架構(gòu)設(shè)計(jì)時(shí),我們需要考慮新的移動(dòng)設(shè)備的計(jì)算能力,而不是那些老的過時(shí)的設(shè)備。
移動(dòng)開發(fā)架構(gòu)設(shè)計(jì)不需要過多考慮設(shè)備的性能
我們從一些測(cè)試中得出的一個(gè)結(jié)論是:現(xiàn)在的移動(dòng)設(shè)備計(jì)算能力都很強(qiáng),運(yùn)行原生應(yīng)用和 HTML 應(yīng)用的效果差別不大,而 HTML 開發(fā)的成本則要比原生開發(fā)小得多。
當(dāng)然這個(gè)結(jié)論在某些領(lǐng)域并不太適用。如果你要開發(fā)一個(gè) 3D 游戲,原生開發(fā)方式能夠帶來更好的游戲體驗(yàn)。但如果你的移動(dòng)應(yīng)用象 Basecamp 一樣側(cè)重信息處理,為了降低開發(fā)成本,你就可以考慮混合開發(fā)方式。我們就是如此,下面是我們?nèi)苿?dòng)產(chǎn)品的發(fā)展軌跡:
第一代產(chǎn)品:原生外殼(native shell)+嵌套WebView
這個(gè)版本就是一個(gè)簡(jiǎn)單的原生外殼負(fù)責(zé)界面導(dǎo)航,嵌套一個(gè) WebView 來顯示 Basecamp Rail application,顯示的基本上都是我們移動(dòng)網(wǎng)站頁(yè)面,再加上一些特殊的樣式。
在移動(dòng)網(wǎng)站的頁(yè)面上嵌套一個(gè)原生的殼,聽起來還是 Web 頁(yè)面,但實(shí)際帶給用戶的體驗(yàn)確是非常不同。用戶可以在 Apple App Store 找到我們的 app,他們一旦登錄 app 后可以再也不用重新登錄(移動(dòng)版本的 Safari 似乎會(huì)經(jīng)常清空 cookie,讓你不得不重新登錄)。我們的 app 大受歡迎,用戶評(píng)分在4和5之間。
整個(gè) app 由一名程序員和一名設(shè)計(jì)師開發(fā),成本不高,因?yàn)槲覀兛梢栽谝延械囊苿?dòng)網(wǎng)站的基礎(chǔ)上開發(fā)。
如果我們當(dāng)初開發(fā)完全原生的 app,用10個(gè)人的團(tuán)隊(duì)1年半的時(shí)間也未必能完成。
第二代產(chǎn)品:原生外殼+原生導(dǎo)航界面

幾個(gè)月前發(fā)布的 Basecamp Android app 是我們的第二代產(chǎn)品,我們?cè)谄渲凶隽舜罅康母倪M(jìn)。
從第一代 iPhone app 中我們感受到了原生導(dǎo)航界面的威力,所以在 Android 版本中,我們由 HTML 頁(yè)面導(dǎo)航轉(zhuǎn)向了原生導(dǎo)航界面。我們從 HTML 頁(yè)面生成原生導(dǎo)航界面,用戶體驗(yàn)更加流暢,原生界面和 HTML 頁(yè)面的體驗(yàn)差別越來越小,甚至很難區(qū)分哪些是原生部分,哪些是 HTML 。
Android 版本是由一兩個(gè)程序員和一個(gè)設(shè)計(jì)師開發(fā)(50%投入)完成的。我們重用了移動(dòng)站點(diǎn)和 iPhone app 中使用的所有 webview,大大提高了開發(fā)效率,同時(shí)用戶也很買賬,超過1000名用戶打了4.5~5的高分。
很多公司在抱怨他們的 iOS 移動(dòng)項(xiàng)目進(jìn)展緩慢,Android 項(xiàng)目似乎更是如此?;蛟S他們已經(jīng)習(xí)慣了 iOS 項(xiàng)目的開發(fā)流程,也許是因?yàn)? Android 的屏幕碎片化問題,但是這些對(duì)我們來說那都不是事。我們推出的 Android app 表現(xiàn)良好,重用了95%的代碼,開發(fā)團(tuán)隊(duì)也一直保持在小規(guī)模。
因地制宜地運(yùn)用原生開發(fā)方式
目前我們正在開發(fā)第三代產(chǎn)品,發(fā)布的平臺(tái)暫時(shí)保密,不過你應(yīng)該也不難猜到。在前兩代產(chǎn)品中,我們?cè)黾恿嗽鷮?dǎo)航界面的使用,同時(shí)進(jìn)一步確定了以 webview 為核心的整體架構(gòu)。在第三代產(chǎn)品中,我們將因地制宜地選擇需要使用原生開發(fā)的功能,好鋼要用在刀刃上。
從之前的100% HTML,到現(xiàn)在的90% HTML +10%原生,我們會(huì)選擇最值得做原生開發(fā)的那10%的部分,最終目的是讓 app 原生部分和 HTML 部分的體驗(yàn)沒有太大區(qū)別。
混合開發(fā)模式使用的技術(shù)
混合開發(fā)模式在技術(shù)很簡(jiǎn)單,主要是處理 webview 的集成、Web 頁(yè)面的加載,以及原生內(nèi)容和 HTML 內(nèi)容之間的交叉鏈接,其實(shí)可能比你想像的還要簡(jiǎn)單得多。
HTML 方面,我們的 Rails Web 應(yīng)用支持 Web 和移動(dòng)兩大平臺(tái),其中 Rails 4.1 feature of variants 起了很大的作用。
這也很大程度上有助于我們發(fā)布新功能。設(shè)想一下如果我們每次需要更新這么多平臺(tái):Rails desktop app, a Rails API app, a client-side MVC app, a mobile web wrapper app, an Android app, and an iPhone app,像我們這樣只有10個(gè)程序員和7個(gè)設(shè)計(jì)師的公司根本無力承擔(dān)如此巨大的工作量。
除了工作量的減輕,bug 修復(fù)效率也提高了,因?yàn)榇蟛糠值拇a邏輯是在 Web 服務(wù)器端,我們可以隨時(shí)修改代碼并發(fā)布,不用通過 Apple App Store 的審批流程。所以我們的移動(dòng) app 和 Web 應(yīng)用一樣,也是持續(xù)部署。
就如我之前提到的,混合模式開發(fā)并不適用于所有情況。在2010年以前,那時(shí)手機(jī)的處理能力都不強(qiáng),所以 HTML/JS 的體驗(yàn)并不好,用戶也不喜歡。但是時(shí)過境遷,現(xiàn)在手機(jī)的處理能力大大提高了,HTML/JS 的性能也不再是一個(gè)問題。
混合開發(fā)模式對(duì)原生開發(fā)模式的挑戰(zhàn)
混合開發(fā)模式在降低開發(fā)復(fù)雜度方面有它的優(yōu)勢(shì),如果你的產(chǎn)品是以顯示和處理信息為主,我認(rèn)為都可以不同程度地采用這個(gè)模式。
對(duì)于小型團(tuán)隊(duì)和公司而言,并不一定需要采用 iOS 原生 app 先行的模式。使用混合模式,不需要你重頭開發(fā)一個(gè) app,這樣可以降低維護(hù)成本,將來擴(kuò)展到其他平臺(tái)也更為方便。
當(dāng)然我知道會(huì)有很多人質(zhì)疑這個(gè)模式,或許因?yàn)樗麄兊?app 中有很多地方需要原生開發(fā)(也許僅僅是他們自己這樣認(rèn)為罷了)。又或許他們已經(jīng)花了很多時(shí)間讓 app 里的 UITableView 看起來非常漂亮,以致如果其他地方不這樣的話顯得不是太完美。再或許大公司就是喜歡耗時(shí)耗力的原生開發(fā),有錢就是這么任性。
無論怎樣,混合開發(fā)當(dāng)下應(yīng)該能夠成為我們移動(dòng)開發(fā)策略的一個(gè)選擇。如果你認(rèn)為這是一個(gè)好的選擇,那么恭喜你,盡情愉快地玩耍吧!
原文鏈接:Hybrid sweet spot: Native navigation, web content
下面補(bǔ)充一些 David 答讀者問:
Mike Waite @ 2014-05-08:我很好奇你是如何決定哪些功能要用原生開發(fā)?
David @ 2014-05-08:主要靠感覺,這畢竟不是一門科學(xué)。如果你感覺你app的某一部分如果用原生開發(fā)會(huì)更好些,可以嘗試做快速原型(spike)。很多 時(shí)候我們通過這種方式證明我們的想法其實(shí)是錯(cuò)的。當(dāng)然如果你需要使用到手機(jī)上的功能如:攝像和其他設(shè)備時(shí),HTML目前還不太適用,不過永遠(yuǎn)也不要把話說 死。
Mike Parsons @ 2014-05-08:好文。很好奇你們是否使用 PhoneGap 或者 Cordova 這樣的框架,或者你們自己開發(fā)了一個(gè)?
David @ 2014-05-08:我們沒有使用任何框架。(此處省去xxx字)
Derick @ 2014-05-08:你怎樣解決 Android 瀏覽器渲染速度慢的問題?這也是 Android 平臺(tái)上更多人傾向開發(fā)原生app得原因。
David @ 2014-05-08:不知道你這個(gè)結(jié)論是近期的還是以前的?Basecamp 的 Android app 在我的 Nexus 5 和 HTC One 上面運(yùn)行得非常流暢。
Derick @ 2014-05-08:就是最近。我猜測(cè)可能和你使用JavaScript的多少有關(guān)系。因?yàn)橐晕覀€(gè)人的經(jīng)驗(yàn),Android 上 JavaScript 的運(yùn)行速度非常慢。如果你感興趣可以看看下面的文章:https://www.timroes.de/2013/11/23/old-webview-vs-chromium-webview/
David @ 2014-05-08:我們使用了很多JavaScript,當(dāng)然沒有 Web MVC 客戶端用得那樣多。另外我們使用了 Turbolinks :)






















