大家好,我是轉轉開放業務部前端負責人張所勇,今天主要來跟大家分享小程式 webview 方面的問題,但我並不會講小程式的 webview 原理,而我主要想講的是小程式內如何嵌入 H5。
那麼好多同學會想了,不就是用 web-view 元件就可以嵌入了嗎,是的,如果我們們的小程式和 H5 的業務比較簡單,那直接用 webview 接入就好了,但我們公司的 H5 除小程式之外,還執行在轉轉 app、58app、趕集 app 等多個端,如何能實現一套程式碼在多端執行,這是我今天主要想分享的,因此今天分享更適合 H5 頁面比較複雜,存在多端執行情況的開發者,期待能給大家提供一些多端相容的思路。
下面我先跟大家介紹下今天演講主要的提綱。
- 小程式技術演進
- webview VS 小程式
- h5 多端相容方案
- 小程式 sdk 設計
- webview 常見問題
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和小程式方向的原創文章。感興趣的同學可以關注一下,如果有問題可以在文章底部留言,我們共同探討。
同時也感謝掘金舉辦了這次大會,讓我有機會同各位同仁進行交流。在未來的前端道路上,與大家共勉!