【Hybrid App】關於Hybrid App技術解決方案的選擇

 

【引言】近年來隨着移動設備類型的變多,操做系統的變多,用戶需求的增長,對於每一個項目啓動前,你們都會考慮到的成本,團隊成員,技術成熟度,時間,項目需求等一堆的因素。所以,開發App的方案已經變得愈來愈多了。曾經有一段HTML5的小浪潮,無數的人蔘與或者看到過一個討論:原生開發仍是混合開發,又或者是Web開發?到底最佳實踐是怎樣的,筆者認爲只有實踐過的人才會知道。尤爲是在這個充滿各類變數的移動互聯網時代。javascript

【摘要】筆者將從Hybrid App的開發現狀出發,闡述Hybrid App的優缺點,同時對比Hybrid AppNative App的各自特性,最後探討一下Hybrid App的新思想方向。css

 

Hybrid App現狀分析

Web App

毫無疑問Web App就是成本最低,最快速地解決方案了。尤爲是近兩年很是流行的響應式設計,Web App市場提供了很是好的實踐場地。最近典型的Web App最佳案例是Sun天氣應用了,其細節處理讓人讚不絕口。html

 

通常來講,擁有下面特色的就是一個Web App了:使用瀏覽器運行;純Web前端架構,不少重要手機特性沒法訪問,例如聯繫人以及Push notification之類的;Single Page App;銷售渠道多限於瀏覽器。jquery

Hybrid App

所謂的Hybrid App其實會有不一樣的分支。並且會和Native應用有重合的地方。下面就說三種不一樣的解決方案。git

方案一:使用PhoneGapAppCan之類的中間件,以WebView做爲用戶界面層,以Javascript做爲基本邏輯,以及和中間件通信,再由中間件訪問底層API的方式,進行應用開發。這種架構通常會很是依賴WebView層的性能。angularjs

 

方案二:使用Adobe Air、RubyMotion、Appcelerator或者是Xamarin這種非官方語言的工具,打包成原生應用的方式開發。爲何筆者會將它們定義爲Hybrid App,主要是它們並無很單純地使用原生提供的語言進行開發,而是經過對開發者提供友好的開發工具,並折中地把這種開發語言轉換成原生語言,最終打包出整個應用,因此也屬於混合應用範疇。github

方案三:在開發原生應用的基礎上,嵌入WebView可是總體的架構使用原生應用提供,通常這樣的開發由Native開發人員和Web前端開發人員組成。Native開發人員會寫好基本的架構以及API讓Web開發人員開發界面以及大部分的渲染。保證到交互設計,以及開發都有一個比較折中的效果出來,優化得好也會有很棒的效果。(當年Facebook Three20就使用該方案)ajax

所以,Hybrid App有如下的特性:

  1. 開發時可能不採用或者大部分不採用原生語言,可是卻有全部原生應用的特性;
  2. 架構方案會和原生有出入,基本由工具而定;
  3. 具備跨平臺特性;
  4. 通常開發相對原生開發的方式要簡單。

Native App

Native App毫無疑問是最可靠的方案。可是學習成本,人才成本,開發效率以及照顧不一樣平臺的特性去考慮,都成爲了開發人員心目中的一道坎。至於說這道坎是不可逾越的仍是一道讓你提升的坎,筆者以爲徹底取決於你本身。基於種種因素的考慮,估計不少人就會選擇折中的方案到了Hybrid App的開發行列當中,包括筆者本身也是這樣過來的。

下面更多的內容都將圍繞Hybrid App開發展開討論。

Hybrid App在開發當中的優勢和缺點

在Hybrid App的開發過程當中,幾種不一樣的方案筆者都有經歷過。固然也經歷到了Native App的開發階段。在如此糾結複雜的過程當中給了筆者很多的經驗,下面筆者也會就自身的經驗和你們分享這些方案當中的優缺點。對於初入行的朋友,筆者是從Web前端入行的,畢竟門檻較低,並且可以快速地培養本身的信心以及對代碼的感受。深刻後就開始接觸到移動開發這塊了。因此會先從Hybrid App的第一種方案提及吧。

方案一(Web架構爲重)

優勢:

  1. 全Web開發,必定程度上有利於Web前端技術人員快速地構建頁面樣式;
  2. 有利於在不一樣的平臺上面展現同一個交互層;
  3. 便於調試,開發的時候能夠經過瀏覽器的方式進行調試,工具豐富。

缺點:

  1. 雖說你能夠專一在界面以及交互開發上了,可是這頁會成爲一個缺點,好比說要仿造一個iOS的默認設置界面,就須要大量的html以及css代碼了,並且效果不必定和iPhone上面的界面同樣好;
  2. 正由於這是跨平臺的開發,因此仍是這句話:兼容是前端的痛。瞭解過在Android機器上面的Web開發就知道這個痛了。好比前些年在Android設備上面寫圓角,border-radius:10px,在Android的設備上面會出現毛邊。
  3. 便於調試實際上是在Web界面層的。可是實際上作Hybrid App開發的時候,你會遇到需求,進入手機的底層請求,作某些處理。好比說若是該應用有Push Notification服務的話,你就須要到底層,獲取Push Notification發生時的數據,以及作相應的交互處理。固然相似PhoneGap這類框架,已經有很好的插件機制去幫助你解決相似的問題,固然還有Game Center之類的插件,具體的話能夠到Github去關注PhoneGap官方的帳戶,資源很是豐富;

方案二(編譯轉換方式)

優勢:

  1. 利用本身熟悉的語言,進行應用開發,好比RubyMotion,就是使用Ruby語言去作iOS開發,開發起來的話,代碼量是數量級地降低啊。
  2. 部分開發工具提供跨平臺的功能,讓你的應用可以快速地發佈到不一樣的平臺上面。好比Mono社區的Xamarin,就是典型的例子了。使用C#語言,可以把你的應用發佈到iOS,Android以及WinPhone市場上面;
  3. 開發出來的程序運行高效。大部分這種架構的應用,其實仍是很是依賴底層的東西的,並且包括界面的東西,都是使用原生的API,效率就固然要比相似於PhoneGap這種架構要好了;

缺點:

嚴重依賴於其工具廠商提供的工具包,調試的時候就要有全套的工具。固然通常來講這些廠商都會以收費的形式發佈他們的工具,相應的也有客服提供技術支持。遇到系統升級,第三方sdk升級,開發工具出現bug等,那麼就要等待工具廠商解決了。至關於把風險壓在對方身上了,本身卻要承擔責任。

方案三(Native架構爲重)

優勢:

  1. 這無疑是最穩定的Hybrid App開發方式了,交互層的效率上由Native的東西解決了,並且架構上基本就是在App內寫網頁,連App Store都是採用了該種方案;
  2. 開發時分工很是明確,底層的由iOS開發人員處理,上層的由Web前端開發人員處理;
  3. 有效的在線參數配置方式,以便於及時在線替換界面;

缺點:

  1. 團隊至少須要兩個工程師,一個是Web的,一個是iOS的。固然若是開發人員會兩種技術也可獨立承擔;
  2. 仍是運行效率,要權衡好多少界面採用Web來渲染,畢竟WebView的效率會相對下降,之前Facebook就是由於Web的渲染效率低下,把整個應用改成原生的解決方案。固然這裏面能夠經過優化來解決。可是優化也是有限度的,如Ruby創始人Matz所說優化要恰當(包括花的時間,技巧等),並且有時候的優化達到的回報率不必定達到你本身的指望。

Hybrid App和Native App開發對比

由於方案三中的思想基本上就是原生應用的開發思想了。這裏要作的對比應該不算大,所以筆者不會作太多的闡述介紹二者的不一樣。可是若是是偏重Web架構的,或者是以方案二這種透過特殊工具開發的,就和原生開發有對比了。此次筆者暫時會以方案一拿來討論。討論中主要會以架構,代碼管理上來討論,固然也會說到部分細節。

架構討論:

由於這是偏重於Web開發的應用,這裏面就須要開發人員有很強烈的大型Web前端架構思想在裏面。提到這裏可能立刻浮如今你腦海中的詞語就是:angular.js,require.js,sea.js,backbone.js等。沒錯,這些工具都可以幫助你快速地梳理好思路,管理好你的Web應用。對開發者最友好的,發揮空間最大的非PhoneGap莫屬了。因此筆者就會以PhoneGap應用展開討論。(由於相似Sencha也有提供方案,可是Sencha自己是一個重量級的框架,並且有本身的思想在裏頭,加上他自己也提供開發工具,在這裏就不適合討論了。對於開發者來講能夠根據本身的需求選擇好工具)

從工具上看:

Angular.js

用於雙向綁定,網絡請求,視圖管理等工做。

Require.js

javascript模塊化工具,在使用較多的交互對象,PhoneGap插件的時候,你就會發現一個強大的模塊化工具會在開發的時候提供極好的幫助。可以幫助你把總體的代碼,管理得層次分明。

Jade Template Engine

模板引擎。筆者我的比較推薦使用Jade,並且筆者本人也在博客中屢次寫到Jade在不一樣場景下使用的技巧的有關文章。主要是jade的語法太簡潔了,並且面向JS開發人員很是友好。若是你尚未開始使用模板引擎,趕忙加入這個隊列吧,你已經落後了。

Jquery Mobile

若是你暫時尚未一個設計師,可是又急於構造一個應用出來。jquery mobile就提供了多套不一樣風格的模板,供你使用,並且還含有不一樣的交互動畫等。並且也是跨平臺的。固然實際場景中,筆者以爲你會花不少時間在寫css上面,由於設計老是天馬行空的。固然你還有不少工具啦,例如sass,以及less.js等。

PhoneGap.js或者Cordova.js

作Phonegap開發必須使用的代碼庫,用於和PhoneGap框架通信。如今這個庫已經更名了,是Cordova。具體爲何更名,得問Adobe咯。

PhoneGap Plugins

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 App來講,其實都有了一些新的解決方案。爲了解決問題其實最終思想都會被還原成如下幾個點上:

  1. 根據需求,選擇工具;
  2. 用適當的工具作適當的事情,有針對性地解決問題;
  3. 世界是平衡的,對於開發者來講,作的有用功越多,用戶體驗就越好,反之越差;
  4. 跨平臺是一個"幌子",什麼都作獲得不表明什麼都作得好

這也是筆者體驗最深的幾個點。並且你會發現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