【引言】近年來隨着移動設備類型的變多,操做系統的變多,用戶需求的增長,對於每一個項目啓動前,你們都會考慮到的成本,團隊成員,技術成熟度,時間,項目需求等一堆的因素。所以,開發App的方案已經變得愈來愈多了。曾經有一段HTML5的小浪潮,無數的人蔘與或者看到過一個討論:原生開發仍是混合開發,又或者是Web開發?到底最佳實踐是怎樣的,筆者認爲只有實踐過的人才會知道。尤爲是在這個充滿各類變數的移動互聯網時代。javascript
【摘要】筆者將從Hybrid App的開發現狀出發,闡述Hybrid App的優缺點,同時對比Hybrid App與Native App的各自特性,最後探討一下Hybrid App的新思想方向。css
毫無疑問Web App就是成本最低,最快速地解決方案了。尤爲是近兩年很是流行的響應式設計,Web App市場提供了很是好的實踐場地。最近典型的Web App最佳案例是Sun天氣應用了,其細節處理讓人讚不絕口。html
通常來講,擁有下面特色的就是一個Web App了:使用瀏覽器運行;純Web前端架構,不少重要手機特性沒法訪問,例如聯繫人以及Push notification之類的;Single Page App;銷售渠道多限於瀏覽器。jquery
所謂的Hybrid App其實會有不一樣的分支。並且會和Native應用有重合的地方。下面就說三種不一樣的解決方案。git
方案一:使用PhoneGap、AppCan之類的中間件,以WebView做爲用戶界面層,以Javascript做爲基本邏輯,以及和中間件通信,再由中間件訪問底層API的方式,進行應用開發。這種架構通常會很是依賴WebView層的性能。angularjs
方案二:使用Adobe Air、RubyMotion、Appcelerator或者是Xamarin這種非官方語言的工具,打包成原生應用的方式開發。爲何筆者會將它們定義爲Hybrid App,主要是它們並無很單純地使用原生提供的語言進行開發,而是經過對開發者提供友好的開發工具,並折中地把這種開發語言轉換成原生語言,最終打包出整個應用,因此也屬於混合應用範疇。github
方案三:在開發原生應用的基礎上,嵌入WebView可是總體的架構使用原生應用提供,通常這樣的開發由Native開發人員和Web前端開發人員組成。Native開發人員會寫好基本的架構以及API讓Web開發人員開發界面以及大部分的渲染。保證到交互設計,以及開發都有一個比較折中的效果出來,優化得好也會有很棒的效果。(當年Facebook Three20就使用該方案)ajax
所以,Hybrid App有如下的特性:
Native App毫無疑問是最可靠的方案。可是學習成本,人才成本,開發效率以及照顧不一樣平臺的特性去考慮,都成爲了開發人員心目中的一道坎。至於說這道坎是不可逾越的仍是一道讓你提升的坎,筆者以爲徹底取決於你本身。基於種種因素的考慮,估計不少人就會選擇折中的方案到了Hybrid App的開發行列當中,包括筆者本身也是這樣過來的。
下面更多的內容都將圍繞Hybrid App開發展開討論。
在Hybrid App的開發過程當中,幾種不一樣的方案筆者都有經歷過。固然也經歷到了Native App的開發階段。在如此糾結複雜的過程當中給了筆者很多的經驗,下面筆者也會就自身的經驗和你們分享這些方案當中的優缺點。對於初入行的朋友,筆者是從Web前端入行的,畢竟門檻較低,並且可以快速地培養本身的信心以及對代碼的感受。深刻後就開始接觸到移動開發這塊了。因此會先從Hybrid App的第一種方案提及吧。
方案一(Web架構爲重)
優勢:
缺點:
方案二(編譯轉換方式)
優勢:
缺點:
嚴重依賴於其工具廠商提供的工具包,調試的時候就要有全套的工具。固然通常來講這些廠商都會以收費的形式發佈他們的工具,相應的也有客服提供技術支持。遇到系統升級,第三方sdk升級,開發工具出現bug等,那麼就要等待工具廠商解決了。至關於把風險壓在對方身上了,本身卻要承擔責任。
方案三(Native架構爲重)
優勢:
缺點:
由於方案三中的思想基本上就是原生應用的開發思想了。這裏要作的對比應該不算大,所以筆者不會作太多的闡述介紹二者的不一樣。可是若是是偏重Web架構的,或者是以方案二這種透過特殊工具開發的,就和原生開發有對比了。此次筆者暫時會以方案一拿來討論。討論中主要會以架構,代碼管理上來討論,固然也會說到部分細節。
由於這是偏重於Web開發的應用,這裏面就須要開發人員有很強烈的大型Web前端架構思想在裏面。提到這裏可能立刻浮如今你腦海中的詞語就是:angular.js,require.js,sea.js,backbone.js等。沒錯,這些工具都可以幫助你快速地梳理好思路,管理好你的Web應用。對開發者最友好的,發揮空間最大的非PhoneGap莫屬了。因此筆者就會以PhoneGap應用展開討論。(由於相似Sencha也有提供方案,可是Sencha自己是一個重量級的框架,並且有本身的思想在裏頭,加上他自己也提供開發工具,在這裏就不適合討論了。對於開發者來講能夠根據本身的需求選擇好工具)
用於雙向綁定,網絡請求,視圖管理等工做。
javascript模塊化工具,在使用較多的交互對象,PhoneGap插件的時候,你就會發現一個強大的模塊化工具會在開發的時候提供極好的幫助。可以幫助你把總體的代碼,管理得層次分明。
模板引擎。筆者我的比較推薦使用Jade,並且筆者本人也在博客中屢次寫到Jade在不一樣場景下使用的技巧的有關文章。主要是jade的語法太簡潔了,並且面向JS開發人員很是友好。若是你尚未開始使用模板引擎,趕忙加入這個隊列吧,你已經落後了。
若是你暫時尚未一個設計師,可是又急於構造一個應用出來。jquery mobile就提供了多套不一樣風格的模板,供你使用,並且還含有不一樣的交互動畫等。並且也是跨平臺的。固然實際場景中,筆者以爲你會花不少時間在寫css上面,由於設計老是天馬行空的。固然你還有不少工具啦,例如sass,以及less.js等。
PhoneGap.js或者Cordova.js
作Phonegap開發必須使用的代碼庫,用於和PhoneGap框架通信。如今這個庫已經更名了,是Cordova。具體爲何更名,得問Adobe咯。
PhoneGap的插件可以幫助你快速地抵達手機的其餘API上面,直接使用Javascript來操控這些底層的API。例如調用Push Notification的相應發生的事件。
從代碼目錄上面看混合應用中的Web層:
/js mainView.js settingView.js networkObject.js renderObject.js /lib /PhoneGapPlugins push-notification-plugin.js pickerView.js PhoneGap.js zepto.js jquerymobile.js iscroll.js angular.js jade.js /css /mainView listItemTemplate.css questionListTemplate.css /settingView /personView /layout navigationBar.css tabButton.css app.css /template /mainView listItemTemplate.txt questionListTemplate.txt /settingView /personView /layout navigationBarTemplate.txt tabButtonTemplate.txt index.html app.js require.js
從代碼的目錄上面看,就是經典的靜態網頁文件的目錄,很是簡單。下面就用一句話來講說整個應用的運做過程吧:
打開PhoneGap應用 ->進入 index.html ->運行require.js ->加載應用資源 -> app.js 控制整個應用 -> angular.js 進行事件綁定以及視圖渲染 ->視圖渲染的時候會將數據和加載好的視圖模板(template目錄下的代碼)處理 ->通過jade模板引擎 ->渲染到相應的位置上
就是如此簡單。
看完了簡單的PhoneGap應用後,筆者們來看看簡單iOS應用在開發時候的代碼目錄吧。思路上仍是很是類似的。在這裏面,筆者不會深刻代碼部分去討論具體的實現以及細節上的東西。
demoApp /Resource navigationBar.png navigationBar@2x.png /demoApp AppDelegate.h AppDelegate.m /SettingViewController settingViewController.h settingViewController.m /MainViewController mainViewController.h mainViewController.m /Supporting Files demoApp-Info.plist InfoPlist.strings ... /plugin /AFNetworking AFHTTPClient.h AFHTTPClient.m AFHTTPRequestOperation.h AFHTTPRequestOperation.m ... /Frameworks CoreData.framework UIKit.framework /Products demoApp.app
Objective-C 是一種通用、高級、面向對象的編程語言。Objective-C是承自Smalltalk的信息傳遞模型(message passing)。Objective-C裏,與其說對象互相調用方法,不如說對象之間互相傳遞信息更爲精確。Objective-C強調面對對象編程,且Objective-C中強制要求將類的(interface)與實現(implementation)分爲兩個部分。類的定義文件遵循C語言之慣例以 .h 爲後綴,實現文件以 .m 爲後綴。因此你會看到大量的類文件在裏頭,整個工程就是有不一樣的類構成的。(固然可能這麼描述不太準確,可是便於你們理解)
這就和豐富的Web前端有很大區別了,在Web前端開發裏有HTML,CSS,JS三劍客,必需要用好這三個東西才能夠把整個應用纔可構建出來。可是在Native應用中,就很單一了。你只須要把握好Objective-C就能夠了。所以對於原生應用來講,開發時只要遵照好規範,即便是一個新手參與開發,也能夠快速地上手,看懂代碼。由於模式已經定好,你們使用同一套的API。按着流程走就行了。固然學習Objective-C須要過程,可是對於擁有C語言,Java語言經驗的開發者來講,是很是簡單的事情。
固然,原生開發的缺點也很明顯了,就是知足不了你的跨平臺需求。
從代碼目錄上面看,其實也基本上看到筆者爲何使用多種JS庫以及框架的緣由了。主要的目的就是爲了構建一個可維護的,具備規範性的Web應用。由於自己Javascript這門語言很是靈活,100我的能夠具備100種風格,加上沒有專門對於Javascript開設的課程,在過往都容易存在對這門語言的誤解。基於種種的緣由,就要約束好一個應用的代碼風格,架構。此外,Javascript自己沒有類的概念,因此在Javascript的面向對象編程中:Javascript的數據和成員封裝很簡單。沒有類,徹底是對象操做。這和Objective-C有很大不一樣。這個時候必需要有一種心態處理好整個Web應用:就是儘量地抽象成對象,你的工做就是對象與對象之間存在交流。
另外有一些點是值得開發者注意的。對於原生應用來講,無論是iOS的,仍是Android的,都會提供一套原生界面的庫。以Objective-C爲例子。若是筆者須要調用Alert,筆者只須要編寫:UIAlertView * alertView = [[UIAlertViewalloc]init];,就把這個view聲明好了。再去執行相應的方法,就能夠了。可是對於Web應用來講,就須要編寫<div id='alertView'><button>肯定</button></div><script>$('#alertView').show();</script>
,一堆的css代碼和html代碼去實現。固然你會詢問筆者,直接寫 alert() 不就能夠了嗎?要是真這麼簡單的話,建議你在iOS的WebView中編寫一下alert,實現:title 是提示,內容是:alert view,肯定按鈕的文字是:好的。你就知道WebView的限制在哪裏了。
所以要完成JS在Web App開發當中的最佳實踐,確定要學習優秀的思想和實現方法了。在這篇文章裏面,筆者們暫時先不去作這種深刻的討論。而是先把例子拋給你們,也許會在下一次討論的時候,再詳細深刻如下這兩個項目。
第一個是斯坦福的iOS開發公開課中的例子,使用objective-c實現,一個簡單的卡牌遊戲。這是經典的mvc開發了。項目地址以下:https://github.com/lbj96347/Stanford-W2013-CardGame,若是您正在使用Mac,那恭喜你,能夠立刻編譯這個遊戲進行測試以及代碼瀏覽。
第二個是使用JavaScript編寫的例子,實現一樣的需求,作一個簡單的卡牌遊戲。可是使用的是HTML+CSS+JS開發。一樣學習了繼承以及mvc的思想。項目地址是:https://github.com/lbj96347/JSMatchismo ,再次恭喜你,無論使用什麼電腦,均可以隨時瀏覽代碼以及運行該遊戲。
這兩年多以來,由於市場的不一樣,也出現了不同的需求,各個技術都有了新的發展。對於Hybrid App來講,其實都有了一些新的解決方案。爲了解決問題其實最終思想都會被還原成如下幾個點上:
這也是筆者體驗最深的幾個點。並且你會發現Hybrid技術也基本在跟隨這幾個點來走。
若是你使用過Jquery Mobile,你作過過場動畫(就是從一個view去到另外一個view),過場動畫在iOS的navigationController中很常見,並且很簡單,效果很好很流暢。在Jquery Mobile中使用ajax,css去實現了,核心代碼可能就幾十行。可能跟iOS裏面的差很少(若是包含動畫),可是實際出來的效果卻差強人意。會出現相似的問題:頁面抖動,感受不連貫,在部分的設備下運行緩慢。若是你的應用要求的體驗並非很高,例如一些新聞展現類應用,更強調排版。這裏小小的體驗差距,就能夠忽略了。(由於英國BBC就是這麼幹的),可是若是你的應用很是強調體驗細節,這裏的解決方案可能就不適合了。或許你要作優化,可是優化的時間可能足以夠你去學習更多的東西了。這樣的話,你是繼續選擇用一個不成熟的工具,仍是選擇去學習一種新的語言呢?因此仍是根據需求而定吧。
另一個例子。曾經有人跟筆者說起到,在使用HTML和CSS編寫應用界面時確實很爽,可是效率不咋的。那爲何不嘗試把應用內容直接搬到Canvas裏面呢?構造一套足夠強大的工具,一套足夠彪悍的UI組件,把整個應用運行於Canvas中。這種想法是很好的,可是其實裏面的短板頁就出現了,Canvas的性能雖高,可是裏面的元素組件多了你能夠保證效果高?全部的東西都會依賴於JavaScript,這對於Javascript來講要構造足夠強悍的面向對象的組件,也非簡單之事,拋棄了CSS和HTML,意味着內部的設計組件可以高度定製,鬆耦合作得很是好。徹底是實現了一套新的xcode和ui庫啊。這就不是在解決一兩個問題了。既然有這麼一個工具,筆者爲何不選擇更好的,例如Xamarin。
作遊戲的朋友估計就深有體會了。爲了解決Canvas性能的問題,愈來愈多的人和應用廠商(尤爲是瀏覽器廠商),提供一種解決方案就是但願將Canvas API和系統底層的API打通。意味着你只須要編寫Canvas代碼,實際作渲染的時候使用的是系統底層的東西,總體上提升了性能。例如Ejectahttp://impactjs.com/ejecta 這個東西。
對於開發人員來講用Javascript編寫遊戲邏輯以及作各類控制都很是舒服,並且由於用的API相同,放到PC上(放開性能問題),一樣能夠運行。這就真的作到了跨平臺,可是又不缺少效率。讓筆者感觸最深的就是@大城小胖在作混合應用(作遊戲)時的作法,小胖的遊戲架構。JS負責邏輯,引擎。JS Binding綁定原生OpenGL,讓原生的來作複雜的渲染處理。HTML CSS能夠處理UI(好比一些Button)。這就是典型的:讓工具去作其擅長的事情。
爲何這麼說?筆者不是一直但願你們可以跨平臺麼?是的。可是要真的認清這個坎。從IE兼容,到目前多個瀏覽器的亂戰,到iOS以及Android設備Web上的兼容,這不就是一個歷史的例子嘛。跨平臺不是很差,只是在一個時代裏,你可以達到怎樣的效果,真的是很難估量的。就比如你出國旅遊,若是兩國關係很是好,並且不少慣例法律一致,對你來講不會形成太多負擔。可是若是語言不同,生活習慣什麼的都不一樣,你就很難適應。一樣是人,你很難在不一樣的環境下生存。真正的跨平臺,就意味着你們求同。這絕對不是一兩天的事情,也非簡單的事情。
那爲何還要跨平臺。業務需求嘛。在這裏必須就要遵照根據需求選擇工具,用適當的工具作適當的事情,根據實際狀況來做開發。若是能夠,筆者以爲頗有必要都瞭解一遍,這樣的話各類開發的思想就會影響到你,你就可以分辨到什麼是好什麼是壞,作更好的選擇。例如筆者剛剛說到的過場動畫的例子。其實徹底可使用筆者說的混合應用中,方案三,去解決這個問題。你無非就是但願用navigationController作一個漂亮的過場動畫嘛,在iOS中幾句代碼就實現了。
再說一個例子吧,若是你正在作一個todo-list的應用,其實無非就是簡單存儲數據以及作一些相關界面渲染。在使用原生的控件的話,有大堆的代碼要寫,並且還要處理好內存問題。可是其實若是使用Web的方式實現,好比backbone.js。整體代碼可能100行左右。就把整個應用實現了,包括本地存儲。你要作的事情就是把整個界面搭建得漂亮些。可能就1個小時的工做。可是若是用原生開發,很難保證到一個小時內完成,由於調試編譯都須要時間吧?何況還有界面呢。
因此要認清跨平臺這個"幌子",並不是全部的問題都用同一個方法處理。筆者們要融匯貫通嘛!
對於作Web App的坑,其實挺多的。這裏沒法一一表達。可是相信實踐過就會知道如何更好地繞過這些坑(例如筆者說的過場動畫的例子)。那麼對於開發者來講要有堅強的毅力,努力去實踐,知足本身永遠不能知足的好奇心,由於最終的經驗會給你帶來不同的感覺,stay hungry。同時筆者們必須保持一顆學習的心,不斷地吸取有養分的思想,學習新的知識,不要太容易知足,stay foolish。每一種語言都會有其中的思想,每一種工具都有本身解決問題的方法論。多嘗試就可以給本身帶來更優秀的架構,更優秀的應用,提供給用戶更好的體驗。固然,也會有更好的回報。
李秉駿(@CashLee李秉駿),HTML5技術活躍分子,HTML5夢工場高級成員,投入Web開發多年。高中開始編寫獨立運營的電子商務網站。近年多進行移動應用先後端的開發,並嘗試將混合應用開發技術運用於實踐當中。
http://www.infoq.com/cn/articles/hybrid-app-development-combat