你們好,我是轉轉開放業務部前端負責人張所勇,今天主要來跟你們分享小程序 webview 方面的問題,但我並不會講小程序的 webview 原理,而我主要想講的是小程序內如何嵌入 H5。前端
那麼好多同窗會想了,不就是用 web-view 組件就能夠嵌入了嗎,是的,若是我們的小程序和 H5 的業務比較簡單,那直接用 webview 接入就行了,但咱們公司的 H5 除小程序以外,還運行在轉轉 app、58app、趕集 app 等多個端,如何能實現一套代碼在多端運行,這是我今天主要想分享的,所以今天分享更適合 H5 頁面比較複雜,存在多端運行狀況的開發者,期待能給你們提供一些多端兼容的思路。vue
下面我先跟你們介紹下今天演講主要的提綱。react
相信在座的不少同窗的產品跟轉轉小程序經歷了相似的發展過程,咱們轉轉小程序是從去年五月份開始開發的,那時候也是小程序剛出來不久,咱們就快速用原生語法搭建了個 demo,功能很簡單,就是首頁列表頁詳情頁。web
而後咱們從7月份開始進入了第二個階段,這時候各類中大型公司已經意識到了,藉助微信的龐大用戶羣,小程序是一個很好的獲客渠道,所以咱們也從 demo 階段正式的開始了小程序開發。小程序
那時候咱們整個團隊從北京跑到廣州的微信園區裏面去封閉開發,咱們一方面在作小程序版本的轉轉,實現了交易核心流程,苦苦的作了兩三個月,DAU 始終也漲不上去,另外一方面咱們也在作不少營銷活動的嘗試,咱們作了一款簡單的測試類的小遊戲,竟然幾天就刷屏了,上百萬的 pv,一方面咱們很欣喜,另外一方面也很尷尬,由於你們都是來玩的,不是來交易的,因此咱們就開始了第三階段。api
這個階段咱們進行了大量的開發工做,讓咱們的小程序功能和體驗接近了轉轉 APP,那到了今年6月份,咱們的小程序進入了微信錢包裏面,咱們的 DAU 峯值也達到了千萬級別,這時候能夠說已經成爲了一個風口上的新平臺,這個時候問題來了,公司的各條線業務都開始想接入到小程序裏面。瀏覽器
因而乎就有了上面這段對話。 因此,爲了可以更好接入各業務線存量 h5 頁面和新的活動頁,咱們開始着手進行多端適配的工做。微信
那咱們會考慮三種開發方案(我這裏只說缺點)cookie
在 webview 這個組件出來之前,咱們是採用第一種方案,用純小程序開發全部業務頁面,那麼適合的框架有如今主流的三種,wepy,mpvue、taro,缺點是不夠靈活,開發成本巨大,真的很累,尤爲是業務方來找咱們想介入小程序,但他們的開發者又不會小程序,當時又不能嵌入 H5,因此業務方都但願咱們來開發,全部業務都來找,大家能夠想一想成本又多高,這個方案確定是不可行,第二種方案,就是一套代碼編譯出多套頁面,在不一樣端運行,mpvue 和 taro 均可以,咱們公司有業務團隊在使用 mpvue,編譯出來的結果不是特別理性,一是性能上面沒有達到理想的狀態,二是 api 在多端兼容上面二次改造的成本很高,各個端 api 差別很大,若是是一個簡單的活動頁還好,但若是是一個跟端有很大功能交互的頁面,那這種方式其實很難實現。app
那咱們採用的是第三種方案,目前咱們的小程序是做爲一個端存在,像 app 同樣,咱們只作首頁、列表、詳情、購買等等核心頁面都是用小程序開發,每一個業務的頁面、活動運營頁面都是H5,而且用 webview 嵌入,這樣各個業務接入的成本很是低,但這也有缺點,一是小程序與 h5 交互和通訊比較麻煩,二是咱們的 app 提供了很大功能支持,這些功能在小程序裏面都須要對應的實現
這張圖是我我的的理解。(並不表明微信官方的見解) 把 webview 和小程序在多個方面作了比對。
將來除了小程序以外,可能會多的端存在,好比智能小程序等等,那咱們指望的結果是什麼呢,就是一套 H5 能運行於各個環境內。
這多是最差的一個 case,h5 判斷所在的環境,去調用不一樣 api 方法,這個 case 的問題是,業務邏輯特別複雜,功能耦合很是嚴重,也基本上沒有什麼複用性。
那咱們轉轉採起的是什麼方案呢?
分三塊,小程序端,用WePY框架,H5這塊主要是vue和react,中間經過一個adapter來鏈接。咱們轉轉的端特別多,除了小程序還包括純轉轉app端,58端,趕集端,純微信端,qq端,瀏覽器端,因此H5頁面須要的各類功能,在每一個端都須要對應的功能實現,好比登陸、發佈、支付、我的中心等等不少功能,這些功能都須要經過adapter這個中間件進行調用,接下來詳細來說。
我這裏就不貼代碼了,我只講下adapter的原理,首先adapter須要初始化,作兩件事情,一是產出一個供h5調用的native對象,二是須要檢測當前所處的環境,而後根據環境去異步加載sdk文件,這裏的關鍵點是咱們要作個api調用的隊列,由於sdk加載時異步的過程,若是期間頁面內發生了api調用,那確定得不到正確的響應,所以你要作個調用隊列,當sdk初始化完畢以後再處理這些調用,其實adapter原理很簡單,若是你想實現多端適配,那麼只須要根據所在的環境去加載不一樣的sdk就能夠了。
作好adapter以後,你須要讓每一個h5的項目都引入adapter文件,而且在調用api的時候,都統一在native對象下面調用。
咱們總結小程序提供給H5的功能大致分爲這四種,第一是基於小程序的五種跳轉能力,好比關閉當前頁面。
那咱們看到小程序提供了這五種跳轉方式。
第二是直接使用微信sdk提供的能力,好比掃碼,這個比較簡單。第三是h5打開小程序的某些頁面,這個是最經常使用的,好比進入下單頁等。
對應每一個api,小程序這邊都須要實現對應的頁面功能,你們看這幾個圖,skipToChat就是進到咱們的IM頁面,下面依次是進入我的主頁,訂單詳情頁,下單頁面,其實咱們的小程序開發的主要工做也是去作這些基礎功能頁面,而後提供給H5,各個業務基本都是H5實現,接入到小程序裏面來,咱們只作一個平臺。
這是進入我的主頁方法的實現,其實就是進入了小程序profile這個頁面。
第四就是h5與小程序直接的通訊能力,這個比較集中體如今設置分享信息和登陸這塊。
上面(adapter)作好了之後,在h5這塊調用就一句話就能夠了。
小程序和h5 之間的通訊基本上經常使用兩種方式,一個是postMessage,這個方法你們都知道,只有在三種狀況才能夠觸發,後退、銷燬和分享,但也有個問題,這個方法是基礎庫1.7.1纔開始支持的,1.7.1如下就只能經過第二種方法來傳遞數據,也就是設置和檢測webview組件的url變化,相似pc時代的iframe的通訊方式。
sdk這塊怎麼作呢,定義一個share方法,首先須要檢測下基礎庫版本,看是否支持postMessage,若是支持直接調用,若是不支持,把分享參數拼接到url當中,而後進行一次重載,因此說經過url傳遞數據有個缺點,就是頁面可能須要刷新一次才能設置成功。
咱們看下分享信息設置這塊,小程序這端,首先經過bindmessage事件接收h5傳回來的數據,而後在用戶分享的時候onShareAppMessage判斷有沒有回傳的數據,若是沒有就到webviewurl當中取,不然就是用默認分享數據。
h5調分享這塊,咱們也作了一些優化,傳統方式是要四步才能調起分享面板,點頁面裏的某個按鈕,而後給用戶個提示層,用戶再去點右上角的點點點,再點轉發,才能拉起分享面板。
咱們後來改爲了這樣,點分享按鈕,把分享信息帶到一個專門的小程序頁面,這個頁面裏面放一個button,type=share,點一下就拉起來面板了,雖然是一個小小的改動,但能大幅提升分享成功率的,由於不少用戶對右上角的點點點不太敏感。
接下來咱們看看登陸功能
分兩種狀況,接入的H5可能一開始就須要登陸態,也可能開始不須要登陸態中途須要登陸,這兩種狀況咱們約定了h5經過本身的url上一個參數進行控制。
一開始就須要登陸態的狀況,那麼在加載webview以前,首先進行受權登陸,而後把登陸信息拼接到url裏面,再去來加載webview,在h5裏面經過adapter來把登陸信息提取出來而且存到cookie裏,這樣h5一進來就是有登錄態的。
一開始不須要登陸態的狀況,一進入小程序就直接經過webview加載h5,h5調用login方法的時候,把needLogin這個參數拼接到url中,而後利用api進行重載,就走了第一種狀況進行受權登陸了。
第一是你如何區分h5所在的環境是小程序裏面的webview仍是純微信瀏覽器,爲何要區分呢,由於你的H5在不一樣環境須要不一樣的api,好比咱們的業務,下單的時候,若是是小程序,那麼咱們須要進入小程序的下單頁,若是是純微信,咱們直接進純微信的下單頁,這兩種狀況的api實現是不同的,那麼爲何難區分,你們可能知道,小程序的組件分爲內置組件和原生組件,內置組件就是小程序定義的view、scroll-view這些基本的標籤,原生組件就是像map啊這種,這實際上是調用了微信的原生能力,webview也是一種相似原生的組件,爲何說是相似原生的組件,微信並無爲小程序專門作一套webview機制,而是直接用微信自己的瀏覽器,因此小程序webview和微信瀏覽器的內核都是同樣的,包括UA頭都是如出一轍,cookie、storage本地存儲數據都是互通的,都是一套,所以咱們很難區分具體是在哪一個環境。
還好微信提供了一個環境變量,但這個變量不是很準確,加載h5之後第一個頁面能夠及時拿到,但後續的頁面都須要在微信的sdk加載完成之後才能拿到,所以建議你們在wx.ready或者是weixinjsbridgeready事件裏面去判斷,區別就在於前者須要加載jweixin.js纔有,但這裏有坑,坑在於h5的開發者可能並不知道你這個檢測過程須要時間,是一個異步的過程,他們可能頁面一加載就須要調用一些api,這時候就可能會出錯,所以你必定要提供一個api調用的隊列和等待機制。
第二個常見問題是支付,由於小程序webview裏面不支持直接調起微信支付,因此基本上須要支付的時候,都須要來到小程序裏面,支付完再回去。
上面作好了之後,在h5這塊調用就一句話就能夠了。
咱們轉轉的業務分兩種支付狀況,一是有的業務h5有本身完善的交易體系,下單動做在h5裏面就能夠完成,他們只須要小程序付款,所以咱們有一個精簡的支付頁,進來直接就拉起微信支付,還有一種狀況是業務須要小程序提供完整的下單支付流程,那麼久能夠直接進入咱們小程序的收銀臺來,圖上就是sdk裏面的基本邏輯,咱們經過payOnly這個參數來決定進到哪一個頁面。
咱們再看下小程序裏面精簡支付怎麼實現的,就是onload以後直接調用api拉起微信支付,支付成功之後根據h5傳回來的參數,若是是個小程序頁面,那直接跳轉過去,不然就刷新上一個webview頁面,而後返回回去。
第三個問題是formId,webview裏面沒有辦法收集formId,這有什麼影響呢,沒有formId就無法發服務通知,沒有服務通知,業務就沒辦法對新用戶進行召回,這對業務來說是一個很大的損失,目前其實咱們也沒有很好的方案收集。
咱們目前主要經過兩種方式收集,訪問量比較大的這種webview落地頁,咱們會作一版小程序的頁面或者作一個小程序的中轉頁,只要用戶有任何觸摸頁面的操做,均可以收集到formId,另一種就是h5進入小程序頁面時候收集,好比支付,IM這些頁面,但並非每一個用戶都會進到這些頁面的,用戶可能一進來看不感興趣,就直接退出了,所以這種方式存在很大的流失。
那怎麼解決這種流失呢,咱們加了一個左上角返回的功能。
首先進入的是一個空白的中轉頁,而後進入h5頁面,這樣左上角就會出現返回按鈕了,當用戶按左上角的返回按鈕時候,頁面會被重載到小程序首頁去,這個看似簡單又微小的動做,對業務其實有很大的影響,咱們看兩個數字,通過咱們的數據統計發現,左上角返回按鈕點擊率高達70%以上,由於這種落地頁通常是被用戶分享出來的,之前純h5的時候只能經過左上角返回,因此在小程序裏用戶也習慣如此,第二個數字,重載到首頁之後,後續頁面訪問率有10%以上,這兩個數字對業務提高其實蠻大的。
其實現原理很簡單,都是經過第二次觸發onShow時進行處理。
以上就是我今天所有演講的內容,謝謝你們!
這是咱們「大轉轉FE」的公衆號。裏面發表了不少FE和小程序方向的原創文章。感興趣的同窗能夠關注一下,若是有問題能夠在文章底部留言,咱們共同探討。
同時也感謝掘金舉辦了此次大會,讓我有機會同各位同仁進行交流。在將來的前端道路上,與你們共勉!