PhoneGap開發(fā)實踐:豆瓣音樂人App
豆瓣音樂人app在2011年開發(fā)時,便采用了基于原生與webapp混合架構的PhoneGap框架,直到今天。這也是目前豆瓣唯一一款使用 PhoneGap的app。最近我們剛發(fā)布了音樂人app的ios新版,仍然保持這一架構,在原生方面的功能上做了一些增強。PhoneGap為音樂人 app的順利發(fā)布帶來很大幫助,當然同時也造成了一些局限。
當時如何做出使用PhoneGap的決定
我們之所以在技術選型時作出這一選擇,主要有以下幾個方面的原因:
-
開發(fā)效率的考慮
盡管豆瓣音樂人的用戶對app有很強的需求,但音樂人app的定位和發(fā)展方向,當時處于不斷探索和快速迭代的階段,這樣的情況意味著,音樂產品線希望使用盡 可能簡單的方式、占用較少的人力資源進行開發(fā),盡快在多個平臺發(fā)布,并且對于迭代的需求能夠快速響應。在各種因素的權衡中,優(yōu)先考慮滿足上述需求。
對 于原生app好還是webapp好這個問題,似乎一直有很大爭議,實際上我不認為這是一個純粹的技術問題。webapp在開發(fā)效率上的優(yōu)勢,原生app在 性能和開發(fā)自由度上的優(yōu)勢,都是不言自明的,一個app是否采用混合架構,在我看來,最重要的因素還是產品定位和發(fā)展策略,如果希望盡快發(fā)布、跨平臺、能 快速響應可以預見的迭代,那么混合架構就很值得考慮。如果有足夠的開發(fā)人員覆蓋各平臺、產品設計成熟度高、產品周期上可接受相對較長的開發(fā)時間,那么原生 顯然是更好的選擇。
-
跨平臺的考慮
豆瓣音樂人會是一個以展示內容和收聽流媒體音樂為主的app,那些只有原生代碼才可以實現(xiàn)的功能,我們需要得比較少。這意味著,如果我們采用混合架構,需要實現(xiàn)的原生特性與需要解決的跨平臺問題會較少,混合架構的優(yōu)勢會被放大。
即 使考慮了第一個因素后認為值得使用混合架構,如果app本身的特性不適合webapp的方式,那也會顯得沒有這個必要。Webapp之所以開發(fā)效率高,一 方面在于html+css+js能做的事情,比用原生代碼做同樣的事情要簡單得多,另一方面在于方便跨平臺。如果app里面要實現(xiàn)的功能,很多都沒法用 html做,必須用原生代碼,那這兩方面的優(yōu)勢都消失殆盡。
實際上,就在我們第一個版本發(fā)布前不久,設計方面進行了一次review,然后對app的整體外觀風格和某些功能與交互做了大幅修改。但其實只用了幾天,設計的修改就被完全實現(xiàn)了,這樣的速度對web前端開發(fā)來說當然不是什么難事,但對原生app來說卻是難以想象的。
App架構與開發(fā)工作流
PhoneGap 只是個原生外殼,app的內核是一個完整的webapp,需要調用的原生功能將以原生插件的形式實現(xiàn),以暴露js接口的方式調用。在webapp框架的選 擇上,我調研了當時的一些專用于webapp的js框架,幾乎都不大成熟,沒什么合適的,當然現(xiàn)在的情況已經(jīng)大不一樣了。由于音樂人app的規(guī)模不算大, 而且在移動設備的webview中性能非常重要,我決定把一些小工具組合成一套微型框架來使用,盡可能優(yōu)化執(zhí)行效率??蚣艽笾掠梢韵滦×慵M成:
- jQuery;
- iScroll4(模擬app風格的滾動);
- js模板機制;
- url分發(fā)與訪問歷史管理;
- 頁面關系與頁面切換機制;
- 基于Jsonp的帶用戶認證的api接口封裝。
這 樣就簡潔地實現(xiàn)了最小化的js框架。之所以使用jsonp的方式通信,是因為我非常希望能使用chrome進行調試,這樣開發(fā)時就很方便,只需要雙擊本地 的html文件,chrome就會成為一個完美的移動設備模擬器,我可以使用自己喜歡的任意前端開發(fā)調試工作流,這比任何移動設備模擬器都要方便得多。
有了框架,接下來只需要一個頁面一個頁面實現(xiàn)就好了,我把webapp部分作為git submodule,ios和android的倉庫都包含它,打包時使用各自的編譯發(fā)布流程即可。
PhoneGap開發(fā)中遇到的問題
大致說一下遇到的印象深刻的問題。其實PhoneGap現(xiàn)在的版本已經(jīng)有很大改進,而且主流手機的性能已經(jīng)比以前好太多,現(xiàn)在新開發(fā)PhoneGap的話,應該會輕松很多。
css3性能問題
我 們開始的設計中,有一些半透明和投影等效果,但我發(fā)現(xiàn)用css3實現(xiàn)后,會導致性能不好,這跟原生開發(fā)時可能遇到的半透明性能問題是一樣的。Webkit 并不如我們想象的那樣有保障。后來,我們?yōu)榇诵薷牧嗽O計,盡可能使用不透明的元素,去掉投影等效果,并減少dom復雜度,性能得到了明顯提升。
像素密度問題
對 于不同像素密度的屏幕,需要準備不同的圖片,然后在css里面使用媒體選擇器,根據(jù) –webkit-device-pixel-ratio,分別插入密度為0.75(老android手機),1(非retina iPhone),1.5(一些android手機),2(retina)的不同css,以使用不同的背景圖片。只需要修改一個css文 件,MakeFile腳本會自動生成其他的幾個css文件。當然,我還需要保證這四套圖片是存在并且正確命名的。
Mp3播放問題
iOS 的webview支持mp3播放是沒有問題的,但當時會有一個限制,就是如果用戶沒有主動操作,webview就不能自動開始播放,為它做一個 workaround也就能夠解決了。比較麻煩的是android的某些較老的版本,雖然支持audio標簽,但是不支持mp3格式的音頻,事實上它不支 持任何格式的音頻。所以對于這種情況,只能使用PhoneGap自帶的音頻播放功能。對用戶而言,效果是一樣的,但這增加了webapp的依賴,使 webapp部分變得復雜了。
不同系統(tǒng)的行為差異
雖然大體上來說,iOS和android使用的webview,其行為都是差不多的,而且由于都是webkit,樣式會非常接近,幾乎是自動完美跨平臺。但是實際開發(fā)中發(fā)現(xiàn),還是會有一些區(qū)別,例如:
- app ready時觸發(fā)的事件不一樣,當然這和PhoneGap封裝有關;
- android有時候會有軟鍵盤問題,有個插件可以解決;
- 處理打開外部url時行為不一致;
- 支持的動畫方式有區(qū)別,對不同平臺需要盡可能使用高效、硬加速的動畫方式。
- 需要為android的幾個實體按鍵寫專門的處理函數(shù)。
仍然需要編寫原生代碼
有的需求在webapp內無法做到,這是經(jīng)常遇到的事。例如:
- 推送消息;
- 狀態(tài)欄提醒;
- 打開內置瀏覽器訪問一些url;
- 綁定社交平臺賬號;
- 緩存下載的圖片和音樂等文件。
很 多都可以找到插件來解決,現(xiàn)在市面上的插件比當時開發(fā)音樂人app最初版本時,已經(jīng)豐富得多了,但仍然可能無法滿足需求,這時就需要自己寫插件來完成,每 出現(xiàn)一個這樣的需求,就意味著要為每個系統(tǒng)做一次原生解決方案。我們正準備把音樂人app中使用的“推薦到社交平臺”的插件進行開源,提供給其他有類似需 求的開發(fā)者使用。
可以移植到更多平臺,但也需要一些工作
我 簡單試過WebOS,樣式上會非常一致,但存在一些其他問題,為穩(wěn)定起見,我們沒有發(fā)布WebOS的打包。另外,移動版IE10已經(jīng)是對標準非常友好的瀏 覽器,但樣式上跟webkit仍然有差異,不能把webkit的webapp直接拿來就用,需要做適配。感覺上又回到了桌面web開發(fā)的世界。
有趣的是,使用MacGap把app核心部分打包成Mac的桌面應用,倒是完全無痛,幾乎直接就可以用。
總結
使用感覺上來說, iOS上的效果要略好于Android上的效果,幾乎跟原生界面沒太大區(qū)別。雖然跟原生app相比,渲染速度等細節(jié)上仍然略微吃虧,但總的看來是完全可以接受的水平。
總結一下的話,我們對基于PhoneGap得到的成果是滿意的,開發(fā)性價比很高。用戶對音樂人app的評價也比較好。將來在產品穩(wěn)定后,我們是否會使用純原生app替代PhoneGap,現(xiàn)在還不知道,這將取決于產品未來的決策。希望得到什么,也就同時決定了會放棄什么,一切都是權衡的結果,框架沒有銀彈。