關於Hybrid的一個分享總結 |
傳送門javascript
1、混合開發背景及概述 |
隨着移動浪潮的興起,各類APP層出不窮,極速的業務擴展提高了團隊對開發效率的要求,這個時候使用IOS&Andriod開發一個APP彷佛成本有點太高了,而H5的低成本、高效率、跨平臺等特性立刻被利用起來造成了一種新的開發模式:Hybrid APP。
做爲一種混合開發的模式,Hybrid APP底層依賴於Native提供的容器(UIWebview),上層使用Html&Css&JS作業務開發,底層透明化、上層多多樣化,這種場景很是有利於前端介入,很是適合業務快速迭代,因而Hybrid火啦。
Hybrid App主要以JS+Native二者相互調用爲主,從開發層面實現「一次開發,多處運行」的機制,成爲真正適合跨平臺的開發。Hybrid App兼具了Native App良好用戶體驗的優點,也兼具了Web App使用HTML5跨平臺開發低成本的優點。css
目前已經有衆多Hybrid App開發成功應用,好比美團、愛奇藝、微信等知名移動應用,都是採用Hybrid App開發模式。html
爲何要引入hybrid開發前端
Native應對急速業務需求,APP迭代加快,頻繁的發版已難以應付
Android渠道衆多,apple store審覈週期長
純native開發效率低,開發維護成本高
不能及時修復bug,不能動態發版
相對於其餘動態發佈技術,技術研發成本較低,使用語言更普遍,社區資源更豐富java
2、Hybrid開發優劣勢 |
三種開發模式對比android
一):Native App 即 原生App開發
優勢ios
(1)打造完美的用戶體驗
(2)性能穩定
(3)操做速度快,上手流暢
(4)訪問本地資源(通信錄,相冊)
(5)設計出色的動效,轉場,
(6)擁有系統級別的貼心通知或提醒
(7)用戶留存率高web
缺點ajax
(1)分發成本高(不一樣平臺有不一樣的開發語言和界面適配)
(2)維護成本高(例如一款App已更新至V5版本,但仍有用戶在使用V2, V3,V4版本,須要更多的開發人員維護以前的版本)
(3)更新緩慢,根據不一樣平臺,提交–審覈–上線 等等不一樣的流程,須要通過的流程較複雜。canvas
二):Web App 即 網頁App開發
一、特色(html css js)
二、優點 (發版徹底自控隨時更新開發成本小時間快)
三、劣勢(性能差弱網絡無網絡條件下體驗差)Web App其實就是寫好的一套長得像App UI界面的可以自適應的網頁加殼。本質套webview殼子打包成App,走的都是web頁面(html css js),這種方式對於作過Web開發的開說很是輕鬆就能夠作出一個屬於本身的App,由於自己來講用的就是Web的東西,因此有很是好的跨平臺的特性能夠在任意平臺運行,包括髮版這方面web能夠隨時部署因此不須要發版,web頁面嵌入webview開發起來速度很是快,一我的就能夠輕鬆搞定,對有展現類需求的項目來講採用這種方式是最適合的,可是若是要實現的功能比較複雜的話就顯得力不從心了。
相比Native App,Web App體驗中受限於網絡環境和渲染性能。
1. 網絡環境,渲染性能
Web APP對網絡環境的依賴性較大,由於Web APP中的H5頁面,當用戶使用時,去服務器請求顯示頁面。若是此時用戶恰巧遇到網速慢,網絡不穩定等其餘環境時,用戶請求頁面的效率大打折扣,在用戶使 用中會出現不流暢,斷斷續續的不良感覺。同時,H5技術自身渲染性能較弱:對複雜的圖形樣式,多樣的動效,自定義字體等的支持性不強。
所以,基於網絡環境和渲染性能的影響,在設計H5頁面時,應注意如下幾點:
1.簡化不重要的動畫/動效
2.簡化複雜的圖形文字樣式
3.減小頁面渲染的頻率和次數
三) :Hybrid App 即 混合型App開發
優勢
一、跨平臺
二、開發週期短、成本低
三、用戶體驗良好
四、能夠即時修復bug、動態發版
缺點
一、雖說你能夠專一在界面以及交互開發上了,可是這頁會成爲一個缺點,好比說要仿造一個iOS的默認設置界面,就須要大量的html以及css代碼了,並且效果不必定和iPhone上面的界面同樣好;
二、正由於這是跨平臺的開發,因此仍是這句話:兼容是前端的痛。瞭解過在Android機器上面的Web開發就知道這個痛了。好比前些年在Android設備上面寫圓角,border-radius:10px,在Android的設備上面會出現毛邊。
三、便於調試實際上是在Web界面層的。可是實際上作Hybrid App開發的時候,你會遇到需求,進入手機的底層請求,作某些處理。好比說若是該應用有Push Notification服務的話,你就須要到底層,獲取Push Notification發生時的數據,以及作相應的交互處理。固然相似PhoneGap這類框架,已經有很好的插件機制去幫助你解決相似的問題,固然還有Game Center之類的插件,具體的話能夠到Github去關注PhoneGap官方的帳戶,資源很是豐富
3、前端與native分工 |
在作Hybrid架構設計以前須要分清Native與前端的界限,首先Native提供的是一宿主環境,要合理的利用Native提供的能力,要實現通用的Hybrid平臺架構,站在前端視角,我認爲須要考慮如下核心設計問題。
交互設計
Hybrid架構設計第一個要考慮的問題是如何設計與前端的交互,若是這塊設計的很差會對後續開發、前端框架維護形成深遠的影響,而且這種影響每每是不可逆的,因此這裏須要前端與Native好好配合,提供通用的接口,好比:
① NativeUI組件,header組件、消息類組件
② 通信錄、系統、設備信息讀取接口
③ H5與Native的互相跳轉,好比H5如何跳到一個Native頁面,H5如何新開Webview作動畫跳到另外一個H5頁面
資源訪問機制
Native首先須要考慮如何訪問H5資源,作到既能以file的方式訪問Native內部資源,又能使用url的方式訪問線上資源;須要提供前端資源增量替換機制,以擺脫APP迭代發版問題,避免用戶升級APP。這裏就會涉及到靜態資源在APP中的存放策略,更新策略的設計,複雜的話還會涉及到服務器端的支持。
帳號信息設計
帳號系統是重要而且沒法避免的,Native須要設計良好安全的身份驗證機制,保證這塊對業務開發者足夠透明,打通帳戶信息。
Hybrid開發調試
功能設計完並非結束,Native與前端須要商量出一套可開發調試的模型,否則不少業務開發的工做將難以繼續,這個不少文章已經接受過了,本文不贅述。
至於Native還會關注的一些通信設計、併發設計、異常處理、日誌監控以及安全模塊由於不是我涉及的領域便不予關注了(事實上是想關注不得其門),而前端要作的事情就是封裝Native提供的各類能力,總體架構是這樣的
4、Hybrid交互設計 |
Hybrid交互有兩種:
一、native主動調用前端js方法主動與前端通訊
二、H5主動與native通訊是經過url schema方式進行的,首先要和native約定好通訊的schema 如:wubacst 而後根據Android和iOS不一樣的通訊方式來分別約定 其中Android是在通訊以前先建立一個iframe經過iframe把拼接好的url請求發送到native或者經過攔截prompt中的消息來和前端通訊 iOS使用了iOS8以上的wkwebview中的messageHandlers的postMessage方法直接把url請求發送到native native接收到前端發送的請求解析以後經過回調函數來通知前端
二者通訊的橋樑都是webview
4.一、Hybrid交互原理
4.1.一、WKWebView+WKScriptMessageHandler實現JS與OC之間互相通訊
iOS 基於WebKit框架的中的WKWebView+WKScriptMessageHandler實現JS與OC之間互相通訊。
總體交互過程分爲三步:
第一:經過- (void)addScriptMessageHandler:(id )scriptMessageHandler name:(NSString *)name,搭建JS調用OC的橋樑,註冊供JS調用的方法name;
第二:JS在調用OC註冊方法只須要:window.webkit.messageHandlers..postMessage()
第三:客戶端在WKScriptMessageHandler代理方法裏收到JS的調用,經過解析處理,並按照事先與FE約定好的的協議作方法的映射,從而達到JS事件的響應。
4.1.二、UIWebview的javaScriptcore方式
將 UIWebViewDelegate 與 UIWebView 拆分紅了14類與3個協議,包含該更細節功能的實現
- (void)evaluateJavaScript:(NSString )javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError _Nullable error))completionHandler
WKWebView :
一、在性能、穩定性、功能方面有很大提高
二、更多的支持 HTML5 的特性
三、官方宣稱的高達60fps的滾動刷新率以及內置手勢
四、Safari 相同的 JavaScript 引擎
4.二、Hybrid通訊機制
4.2.一、總體設計
4.2.二、native與js通訊流程
4.2.三、js與native交互流程
相似於JOSNP跨域原理
APP在安裝以後會註冊私有協議到OS,瀏覽器自身不能識別的協議時,會將連接拋給OS,轉爲APP處理
好比itunes://開頭的連接是Apple Store的私有協議,支付寶的私有協議alipay://,騰訊的tencent://等等
固定協議:webview.loadUrl(「javascript: alert(‘hello world’)」);
5、交互協議設計 |
5.一、API式交互
調用native API接口方式和咱們請求服務端的ajax方式相似,都是前端主動去發送一個請求,被接收處理後返回回調
5.二、交互數據格式約定
混合開發中交互種類繁多,如何作到通用
以58同城車商通app爲例:
頁面跳轉類型
wubacst://jumppage/…?query=…
native組件處理類型
wubacst://handlejs/…?query=…
5.三、前端協議封裝
前面提到過,Android和iOS對於前端的交互是有區別的,雖然都是採用URL攔截的方式,可是具體的方式是不同的;iOS採用WKwebview中的messageHandlers方法,而Android採用相似ajax同樣的請求;可是對於業務放來講,在和native通訊時是不區分端的,這就須要封裝一個交互協議的API來提供給業務方,在協議API中來區分處理Android和iOS的交互;
處理源碼以下:
//區分處理Android和iOS _nativeBridge: function(param) { "android" == this.os ? this._andr4Native(param) : "ios" == this.os ? this._ios4Native(param) : "ipad" == this.os && this._ios4Native(param) },
Android客戶端處理
_createIframe: function() { var iFrame; return iFrame = document.createElement("iframe"), iFrame.setAttribute("style", "display:none;"), iFrame.setAttribute("height", "0px"), iFrame.setAttribute("width", "0px"), iFrame.setAttribute("frameborder", "0"), iFrame } //開始是使用iframe和Android客戶端通訊 後來改爲了prompt _andr4Native: function(param) { var host = param.host; var path = param.path; var query = param.query; query = JSON.stringify(query) //3.5.0以上版本Android端都走新的攔截方式 var url = "wubacst://" + host + "/" + path + "?query=" + encodeURIComponent(query); if(this._versionCompare(this._getVersion(),'3.5.0')){ window.prompt(url) }else{ if (!this.domReady) return void this.actionPreQueue.push(param); this.andrFrame = this._createIframe(), this.andrFrame.src = "wubacst://" + host + "/" + path + "?query=" + encodeURIComponent(query), document.body.appendChild(this.andrFrame), this.andrFrame = null } }
iOS客戶端處理
//messageHandlers上綁定的WBcheshangtong對象是和iOS約定好的 _ios4Native: function(param) { var host = param.host; var path = param.path; var query = param.query; query = JSON.stringify(query); var url = "wubacst://" + host + "/" + path + "?query=" + encodeURIComponent(query); if (window.webkit) { try { window.webkit.messageHandlers.WBcheshangtong.postMessage(url); } } }
處理好底層交互以後,在根據業務的不一樣,前端封裝一些通用的協議,如:
整個通訊協議API以下:
app58.prototype = {
init: function() {}, _nativeBridge: function(param){}, _ios4Native: function(param){}, _andr4Native: function(param){}, _createIframe: function(){}, loadPage: function(path, url, jumpParameter,title,titleColor,isDestoryBeforePage){} ... } var WBAPP = new app58(window.app_config || null)
6、問題總結 |
6.一、iOS cookie丟失問題
目前來講WKwebview還不是那麼穩定,常常會出現前端cookie丟失問題,一下是本人在開發過程當中解決問題的一個過程:
最終是用hookAjax來實現的
hookAjax的原理就是攔截全部的網絡請求,代理send方法實現本身的目的
有興趣的能夠去看看hookajax 這裏就再也不詳細講解了
6.二、Android通訊協議重複提交 因爲Android使用的是iframe發送請求和Android客戶端進行交互的,在前端使用canvas時,iframe重複執行,致使前端重複提交協議,目前換成了prompt交互;在開發過程當中有遇到這種問題的小夥伴,歡迎留言。