這篇文章主要是對小程序官方文檔作部分深刻解讀;讓你們瞭解小程序實現背後的機制原理。
因爲筆者沒有獲取到微信官方提供的小程序實現原理圖,不少內容都是經過閱讀文檔資料反推和理解所得,若有誤解之處,望指正。
本文建議閱讀時間: 5minjavascript
wx
對象JsBridge
JsBridge
實現思路JsBridge
的實現官方文檔稱其爲「基礎庫」。html
這是一個很寬泛的名詞,只是以爲很重要,但說很差它具體有什麼做用。我總結了小程序5月帶給個人驚喜,它支持的功能也愈來愈豐富,體驗也越變越好,而這些動做若是用專業一點的術語歸納就是「升級基礎庫」。
微信從開放內測到如今,微信基礎庫已經從的 v1.0.0 升級到了 v1.3.0 。
那麼,「基礎庫」究竟是什麼東西? java
小程序基礎庫提供豐富的微信原生API,能夠方便的調起微信提供的能力,如獲取用戶信息,本地存儲,支付功能等。web
這是官方對於「基礎庫」的定義。咱們知道小程序的開發十分相似於如今的移動web開發,而移動web能使用到手機系統功能,app特點功能是很是有限的,而「基礎庫」的做用就是爲了拓展小程序這方面能力,讓其功能與表現更接近原生app。小程序
咱們發現「基礎庫」的功能和微信的 JS-SDK 十分相似,順便再回顧下微信 JS-SDK 又是作什麼的呢? 微信小程序
微信 JS-SDK 是微信公衆平臺面向網頁開發者提供的基於微信內的網頁開發工具包。經過使用微信 JS-SDK ,網頁開發者可藉助微信高效地使用拍照、選取圖片、語音、位置等手機系統的能力,同時能夠直接使用微信分享、掃一掃、卡券、支付等微信特點功能,爲微信用戶提供更優質的網頁體驗。api
window
能力;官方API : getSystemInfo
、getSystemInfoSync
。移動web開發
wx.getSystemInfo({
success: function(obj) {
obj = obj || {};
console.log('SDKVersion: ', obj.SDKVersion);
},
fail: function() {
console.error('[error]: getSystemInfo failed.');
}
});複製代碼
返回對象中SDKVersion
的值就是該微信版本攜帶的小程序基礎庫的版本號。
注意:該屬性在小程序版本 v1.1.0 纔開始支持。數組
小程序的能力須要微信客戶端來支撐,每個基礎庫都只能在對應的客戶端版本上運行,高版本的基礎庫沒法兼容低版本的微信客戶端。緩存
官方的這種說法存在一些問題。如今基礎庫版本和客戶端版本並非一一對應關係。客戶端能夠主動升級小程序基礎庫版本達到灰度上線新版的目的,因此必然存在一個客戶端版本對應多個基礎庫版本的狀況。
爲了不新版本的基礎庫給線上小程序帶來未知的影響,微信客戶端都是攜帶 上一個穩定版 的基礎庫發佈的。
在新版本客戶端發佈後,咱們再經過後臺灰度新版本基礎庫,灰度時長通常爲 12 小時,在灰度結束後,用戶設備上纔會有新版本的基礎庫。
以微信 6.5.8 爲例,客戶端在發佈時攜帶的是 1.1.1 基礎庫(6.5.7上已全量的穩定版)發佈,在 6.5.8 發佈後,咱們再經過後臺灰度 1.2.0 基礎庫。
筆者使用的IOS設備更新到v6.5.8時對應的 SDKVersion 是 1.2.0, 但截止發稿日,該值已經變成了 1.2.4。
「細思恐極」,若是咱們已經完成一臺裝有 6.5.4 版本微信的Oppo手機對小程序的兼容測試,頗有可能過幾天這臺Oppo手機將小程序基礎庫更新到新版本致使小程序不可用。
建議:瞭解產品的用戶手機微信版本分佈,肯定迴歸覆蓋範圍,完成迴歸測試。
這是咱們點餐小程序中用戶各版本微信的佔比圖。經過這兩張圖咱們可以清晰的得出目前用戶使用的微信版本分佈,就可以制定針對性的測試覆蓋方案。
在 基礎庫更新時機 那小結咱們提到,小程序的基礎庫和微信版本並非一一對應關係,且隨着基礎庫和微信的不斷升級,它們的對應關係在時刻發生着變化。
下面是我整理的小程序基礎庫和微信版本對應表。
wx
對象小程序基礎庫的全部功能所有封裝在 wx
全局對象中,開發者能夠在小程序邏輯層代碼的任何地方調用該對象的方法。
看到 wx
對象,使用過 JS-SDK 的朋友表示很熟悉。咱們在前面章節 小程序基礎庫與JS-SDK 對它們作了簡單的比較,下面深刻學習它們出於同源的技術:JsBridge
。
下一節,咱們詳細講解一下JsBridge
的原理和實現。
JsBridge
Native層須要暴露一些方法給js調用,好比,彈Toast提醒,彈Dialog,分享等等,有時候甚至把h5的網絡請求放着native去完成。緣由很簡單,Native有更好的性能,更一致的表現和體驗。這就是 JsBridge
技術。
webview是客戶端的一個可調用的組件,且客戶端能夠對webview作函數,事件的封裝,能夠攔截webview的請求作統一控制,也能夠向webview注入方法供JS調用等。
JsBridge
實現思路JavascriptInterface
接口;經過這些方式可以實現JS和客戶端通訊,調起客戶端以及手機系統能力。
JsBridge
的實現 wx
就是客戶端暴露給小程序的JsBridge
接口。而這個封裝的JsBridge
很是強大,它不只僅支持toast,彈框等簡單功能,甚至包括網路request
請求,緩存操做,手機硬件設備藍牙、重力感應等。下一個章節,咱們介紹微信如何使用 JsBridge
、視圖層、邏輯層交互操做。
這張圖展現了視圖層、邏輯層之間通訊方式,以及JsBridge
起到紐帶的做用。咱們能夠作如下幾點總結:
JsBridge
一方面傳遞基礎功能,另外一方面作視圖層和邏輯層的數據傳遞工做;三端的js執行環境以及用於渲染非原生組件的環境是各不相同的:
- 在 iOS 上,小程序的 javascript 代碼是運行在 JavaScriptCore 中,是由 WKWebView 來渲染的;
- 在 Android 上,小程序的 javascript 代碼是經過 X5 JSCore來解析,是由 X5 基於 Mobile Chrome 53 內核來渲染的;
- 在 開發工具上, 小程序的 javascript 代碼是運行在 nwjs 中,是由 Chrome Webview 來渲染的;
這是官方關於視圖層和邏輯層運行環境的介紹。
視圖層(不包括Native組件)在webview組件中渲染;邏輯層的js代碼則經過js容器來執行。js代碼執行過程當中能夠經過JsBridge調起微信、系統的能力,也能夠將數據經過setData()
函數傳遞給視圖層作渲染。視圖層在渲染和交互過程當中能夠經過事件與客戶端進行通訊。
視圖層向邏輯層的通訊由事件來完成,而邏輯層數據向視圖層發送渲染指令是經過Page的setData
函數。下面咱們詳細說明他們的細節原理;
這張生命週期圖很是詳盡的描述了一個頁面從建立入棧、數據交互、銷燬出棧的整個過程。在頁面渲染和使用過程當中會出現大量的事件,而這些事件會被JsBridge捕獲到,並傳遞給邏輯層處理,主要包括:生命週期事件、UI事件。
視圖進程在完成階段性工做後,須要向邏輯層同步其當前狀態以便邏輯層作出應對策略。主要包括:onLoad
、onReady
、onShow
、onHide
、onUnload
、onPullDownRefresh
、onReachBottom
、onShareAppMessage
等。
視圖層向邏輯層的通訊方式。
這類事件綁定在組件上,觸發則能夠將用戶的行爲反饋到邏輯層對應的註冊函數,如bindtap
、bindinput
、bindconfirm
、bindfocus
、bindsubmit
、bindchange
、bindlinechange
等
邏輯層向視圖層發送渲染指令的方式。
setData
函數用於將數據從邏輯層發送到視圖層,同時改變對應的 this.data 的值。
注意:data 將會以 JSON 的形式由邏輯層傳至渲染層,因此其數據必須是能夠轉成 JSON 的格式:字符串,數字,布爾值,對象,數組。
從性能角度考慮,UI渲染是比較耗時的,一方面儘可能減小頁面渲染操做,另外一方面其會對data的內容作深層次diff,儘可能控制data的大小和數據結構的深度(官方限制data數據量最大爲1024K。
筆者在作小程序性能監控的時候,遇到的一個問題就是沒法準確統計到頁面渲染完成的時間。緣由是 setData
函數只負責發送數據和渲染指令,但並無對應的反饋通知。
經過仔細分析,微信實際上是能夠提供這樣的能力的,在視圖層完成渲染後經過某種方式再告知邏輯層渲染狀態,我想出了兩個解決方案:
在和騰訊的同事提出該建議後,他們給出否認答案。緣由是:回調函數會增長一次渲染層到邏輯層的通訊開銷,而這個開銷相對而已比較重,目前他們官方是作了一些數據採樣,下圖是他們發給咱們的渲染結果。
本文經過對小程序基礎庫的介紹、拓展 JsBridge
到融會貫通,介紹基礎庫、視圖層、邏輯層的運行機制,就是但願你們可以創建對小程序架構理解,瞭解各模塊在框架中所處位置和功用。
以上均爲我的理解所得,因爲沒有一些系統學習客戶端開發webview的經驗,因此關於 JsBridge
的一些講解比較淺顯,若有不當言論,望指出,謝謝。
-做者介紹-J文,美團點評點餐終端團隊C端組成員,負責大衆點評雲餐廳微信小程序開發。