- 原文:小程序webview實踐
- 作者:張所勇(轉轉開放業務部前端負責人)
- 公眾號:大轉轉FE
Fundebug經授權轉載,版權歸原作者所有。
大家好,我是轉轉開放業務部前端負責人張所勇,今天主要來跟大家分享小程序 webview 方面的問題,但我並不會講小程序的 webview 原理,而我主要想講的是小程序內如何嵌入 H5。
那么好多同學會想了,不就是用 web-view 組件就可以嵌入了嗎,是的,如果咱們的小程序和 H5 的業務比較簡單,那直接用 webview 接入就好了,但我們公司的 H5 除小程序之外,還運行在轉轉 app、58app、趕集 app 等多個端,如何能實現一套代碼在多端運行,這是我今天主要想分享的,因此今天分享更適合 H5 頁面比較復雜,存在多端運行情況的開發者,期待能給大家提供一些多端兼容的思路。
下面我先跟大家介紹下今天演講主要的提綱。
1 轉轉小程序演進過程
相信在座的很多同學的產品跟轉轉小程序經歷了類似的發展過程,我們轉轉小程序是從去年五月份開始開發的,那時候也是小程序剛出來不久,我們就快速用原生語法搭建了個 demo,功能很簡單,就是首頁列表頁詳情頁。
然后我們從7月份開始進入了第二個階段,這時候各種中大型公司已經意識到了,借助微信的龐大用戶群,小程序是一個很好的獲客渠道,因此我們也從 demo 階段正式的開始了小程序開發。
那時候我們整個團隊從北京跑到廣州的微信園區里面去封閉開發,我們一方面在做小程序版本的轉轉,實現了交易核心流程,苦苦的做了兩三個月,DAU 始終也漲不上去,另一方面我們也在做很多營銷活動的嘗試,我們做了一款簡單的測試類的小游戲,居然幾天就刷屏了,上百萬的 pv,一方面我們很欣喜,另一方面也很尷尬,因為大家都是來玩的,不是來交易的,所以我們就開始了第三階段。
這個階段我們進行了大量的開發工作,讓我們的小程序功能和體驗接近了轉轉 APP,那到了今年6月份,我們的小程序進入了微信錢包里面,我們的 DAU 峰值也達到了千萬級別,這時候可以說已經成為了一個風口上的新平台,這個時候問題來了,公司的各條線業務都開始想接入到小程序里面。
於是乎就有了上面這段對話。 所以,為了能夠更好接入各業務線存量 h5 頁面和新的活動頁,我們開始着手進行多端適配的工作。
那我們會考慮三種開發方案(我這里只說缺點)
在 webview 這個組件出來以前,我們是采用第一種方案,用純小程序開發所有業務頁面,那么適合的框架有現在主流的三種,wepy,mpvue、taro,缺點是不夠靈活,開發成本巨大,真的很累,尤其是業務方來找我們想介入小程序,但他們的開發者又不會小程序,當時又不能嵌入 H5,所以業務方都希望我們來開發,所有業務都來找,你們可以想想成本又多高,這個方案肯定是不可行,第二種方案,就是一套代碼編譯出多套頁面,在不同端運行,mpvue 和 taro 都可以,我們公司有業務團隊在使用 mpvue,編譯出來的結果不是特別理性,一是性能上面沒有達到理想的狀態,二是 api 在多端兼容上面二次改造的成本很高,各個端 api 差異很大,如果是一個簡單的活動頁還好,但如果是一個跟端有很大功能交互的頁面,那這種方式其實很難實現。
那我們采用的是第三種方案,目前我們的小程序是作為一個端存在,像 app 一樣,我們只做首頁、列表、詳情、購買等等核心頁面都是用小程序開發,每個業務的頁面、活動運營頁面都是H5,並且用 webview 嵌入,這樣各個業務接入的成本非常低,但這也有缺點,一是小程序與 h5 交互和通信比較麻煩,二是我們的 app 提供了很大功能支持,這些功能在小程序里面都需要對應的實現
2 webview VS 小程序
這張圖是我個人的理解。(並不代表微信官方的看法) 把 webview 和小程序在多個方面做了比對。
3 h5多端兼容方案
未來除了小程序之外,可能會多的端存在,比如智能小程序等等,那我們期望的結果是什么呢,就是一套 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對象下面調用。
4 小程序sdk設計
我們總結小程序提供給H5的功能大體分為這四種,第一是基於小程序的五種跳轉能力,比如關閉當前頁面。
那我們看到小程序提供了這五種跳轉方式。
第二是直接使用微信sdk提供的能力,比如掃碼,這個比較簡單。第三是h5打開小程序的某些頁面,這個是最常用的,比如進入下單頁等。
對應每個api,小程序這邊都需要實現對應的頁面功能,大家看這幾個圖,skipToChat就是進到我們的IM頁面,下面依次是進入個人主頁,訂單詳情頁,下單頁面,其實我們的小程序開發的主要工作也是去做這些基礎功能頁面,然后提供給H5,各個業務基本都是H5實現,接入到小程序里面來,我們只做一個平台。
這是進入個人主頁方法的實現,其實就是進入了小程序profile這個頁面。
第四就是h5與小程序直接的通信能力,這個比較集中體現在設置分享信息和登錄這塊。
4.1 設置分享
上面(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,點一下就拉起來面板了,雖然是一個小小的改動,但能大幅提高分享成功率的,因為很多用戶對右上角的點點點不太敏感。
4.2 登錄
接下來我們看看登錄功能
分兩種情況,接入的H5可能一開始就需要登錄態,也可能開始不需要登錄態中途需要登錄,這兩種情況我們約定了h5通過自己的url上一個參數進行控制。
- 一開始就需要登錄態的情況,那么在加載webview之前,首先進行授權登錄,然后把登錄信息拼接到url里面,再去來加載webview,在h5里面通過adapter來把登錄信息提取出來並且存到cookie里,這樣h5一進來就是有登陸態的。
- 一開始不需要登錄態的情況,一進入小程序就直接通過webview加載h5,h5調用login方法的時候,把needLogin這個參數拼接到url中,然后利用api進行重載,就走了第一種情況進行授權登錄了。
5 webview常見問題
5.1 區分環境
第一是你如何區分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調用的隊列和等待機制。
5.2 支付
第二個常見問題是支付,因為小程序webview里面不支持直接調起微信支付,所以基本上需要支付的時候,都需要來到小程序里面,支付完再回去。
上面做好了以后,在h5這塊調用就一句話就可以了。
我們轉轉的業務分兩種支付情況,一是有的業務h5有自己完善的交易體系,下單動作在h5里面就可以完成,他們只需要小程序付款,因此我們有一個精簡的支付頁,進來直接就拉起微信支付,還有一種情況是業務需要小程序提供完整的下單支付流程,那么久可以直接進入我們小程序的收銀台來,圖上就是sdk里面的基本邏輯,我們通過payOnly這個參數來決定進到哪個頁面。
我們再看下小程序里面精簡支付怎么實現的,就是onload之后直接調用api拉起微信支付,支付成功以后根據h5傳回來的參數,如果是個小程序頁面,那直接跳轉過去,否則就刷新上一個webview頁面,然后返回回去。
5.3 formId收集
第三個問題是formId,webview里面沒有辦法收集formId,這有什么影響呢,沒有formId就沒法發服務通知,沒有服務通知,業務就沒辦法對新用戶進行召回,這對業務來講是一個很大的損失,目前其實我們也沒有很好的方案收集。
我們目前主要通過兩種方式收集,訪問量比較大的這種webview落地頁,我們會做一版小程序的頁面或者做一個小程序的中轉頁,只要用戶有任何觸摸頁面的操作,都可以收集到formId,另外一種就是h5進入小程序頁面時候收集,比如支付,IM這些頁面,但並不是每個用戶都會進到這些頁面的,用戶可能一進來看不感興趣,就直接退出了,因此這種方式存在很大的流失。
5.4 左上角返回
那怎么解決這種流失呢,我們加了一個左上角返回的功能。
首先進入的是一個空白的中轉頁,然后進入h5頁面,這樣左上角就會出現返回按鈕了,當用戶按左上角的返回按鈕時候,頁面會被重載到小程序首頁去,這個看似簡單又微小的動作,對業務其實有很大的影響,我們看兩個數字,經過我們的數據統計發現,左上角返回按鈕點擊率高達70%以上,因為這種落地頁一般是被用戶分享出來的,以前純h5的時候只能通過左上角返回,所以在小程序里用戶也習慣如此,第二個數字,重載到首頁以后,后續頁面訪問率有10%以上,這兩個數字對業務提升其實蠻大的。
其實現原理很簡單,都是通過第二次觸發onShow時進行處理。
以上就是我今天全部演講的內容,謝謝大家!
這是我們“大轉轉FE”的公眾號。里面發表了很多FE和小程序方向的原創文章。感興趣的同學可以關注一下,如果有問題可以在文章底部留言,我們共同探討。
同時也感謝掘金舉辦了這次大會,讓我有機會同各位同仁進行交流。在未來的前端道路上,與大家共勉!