整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          今天是學習前端的第一天之小程序的雙線程架構

          微信小程序的誕生

          小程序是期望的產物。

          在沒有小程序的時候,企業們都在微信用什么?答案是H5。因為公眾號,公眾號是小程序的前身,但H5也有自己的缺點,無法自己獲取很多底層 APP 擁有的功能。

          隨著微信提供一系列的JS-SDK給Web開發使用,(JS-SDK就是一套調用微信能力的工具包。比如微信支付等等的微信功能)

          WebView 的使用頻率越來越高。而Webview的加載體驗相對比較糟糕。

          微信作為一個平臺,具有優化用戶體驗的責任。微信面臨的問題是如何設計一個比較好的系統,使得所有開發者在微信中都能獲得比較好的體驗。這個問題是之前的 JS-SDK 所處理不了的,需要一個新的系統來完成。小程序就是在這種期待中誕生的。

          一方面,小程序是基于 WebView 開發的,其目的是減少開發的成本,實現異步加載的方式,允許開發者在線的版本更新和 Bug 修復,而前面說的使用 Webview 容易導致加載體驗不好,小程序使用了雙線程的方式來使頁面渲染和邏輯代碼加載分開,降低頁面卡殼的可能性。

          小程序與web開發的區別

          我們都知道,傳統web的架構模型是單線程架構,其渲染線程和腳本線程是互斥的,這也就是說為什么長時間的腳本運行可能會使頁面失去響應,而小程序的架構模型有別于傳統web,小程序為雙線程架構,其渲染線程和腳本線程是分開運行的。

          傳統web開發者可以使用各種瀏覽器暴露出來的DOM API來進行DOM操作,但由于小程序的邏輯層和渲染層是分開的,邏輯層并沒有一個完整的瀏覽器對象,因而缺少相關的DOM API和BOM API

          傳統web開發者需要面對的是各式各樣的瀏覽器,PC 端需要面對 IE、Chrome、火狐瀏覽器等,在移動端需要面對Safari、Chrome以及 iOS、Android 系統中的各式 WebView 。而小程序開發過程中需要面對的是兩大操作系統 iOS 和 Android 的微信客戶端,以及用于輔助開發的小程序開發者工具。

          各平臺的腳本執行環境以及渲染非原生組件的環境都是各不相同的,如下表所示:

          平臺渲染層邏輯層

          iOS

          JsCore

          Android

          定制內核

          V8

          小程序開發者工具

          Chrome WebView

          NWJS

          雙線程架構

          小程序的渲染層和邏輯層分別由2個線程管理:渲染層的界面使用了WebView 進行渲染,邏輯層采用JsCore線程運行JS腳本。

          小程序中為了達到多頁面體驗的功能,需要使用到多個WebView,每個WebView對應的就是一個小程序的頁面。WebView和JsCore這兩個線程的通信會經由微信客戶端(下文中也會采用Native來代指微信客戶端)做中轉,線程之間的通訊、數據的傳遞以及邏輯層發送網絡請求也都是經由Native轉發,小程序的通信模型下圖所示。

          在這里插入圖片描述

          WebView是什么

          這里需要解釋一下WebView是什么,WebView直譯是網頁視圖,我們可以簡單地看作一個可以嵌套到界面上的一個瀏覽器控件。

          我們通常是用瀏覽器來瀏覽網頁,你很清楚的知道你正在使用瀏覽器,要么是PC客戶端,要么是手機上的app。但是webview是一個嵌入式的瀏覽器,是嵌入在原生應用中的,你可能都意識不到你在用瀏覽器。傳統瀏覽器分為兩個部分,UI(地址欄、導航欄)和瀏覽器引擎。webview就是原生應用中的瀏覽器引擎。

          簡單來說 webview 是手機中內置了一款高性能 webkit 內核瀏覽器,不過沒有提供UI(地址欄、導航欄),只是單純的展示一個網頁界面。

          為什么要多個WebView

          接著上文說,那么為什么要用多個WebView呢?多個WebView可以理解為多頁面應用,其實是有區別于單頁面應用SPA的,SPA渲染頁面是通過路由識別以后去動態地將頁面掛載到root節點里,如果SPA打開一個新頁面,是需要卸載掉當前的頁面,然后重新渲染。很顯然,只有通過多個WebView才能更加接近原生應用APP的用戶體驗。

          管控與安全

          微信小程序是什么架構_微信小程序架構_微信小程序系統架構

          雙線程架構的另一個好處就是安全管控。我們都知道基于web技術來渲染小程序,是存在一些不可控因素和安全風險的。因為web技術非常靈活開放,我們可以使用去任意地控制頁面的跳轉或者改變頁面上的任何內容,還可以通過操作DOM,直接獲取小程序內部的一些敏感數據,比如用戶信息等等,那么小程序將毫無安全可言。

          為了解決安全管控的問題,小程序從設計上就阻止了開發者去使用一些瀏覽器提供的開放性api,比如說跳轉頁面、操作DOM等等。如果把這些東西一個一個地去加入到黑名單,那么勢必會陷入一個非常糟糕的循環,因為瀏覽器的接口也非常豐富,那么就很容易遺漏一些危險的接口,而且就算是禁用掉了所有的接口,也防不住瀏覽器內核的下次更新。

          所以要徹底解決這個問題,我們可以使用客戶端系統的 引擎 (iOS下使用 框架,安卓下使用騰訊 x5 內核提供的 JsCore 環境),通過提供一個沙箱環境來運行開發者的 代碼。這個沙箱環境只提供純 的解釋執行環境,沒有任何瀏覽器相關接口。

          這就是小程序雙線程模型的由來:

          雙線程通信

          既然渲染層和邏輯層分別由兩個線程管理,那么二者之間的交互就涉及到線程間的通信過程了。二者通信過程如下圖所示:

          在這里插入圖片描述

          可以看出,線程的通信是通過Native做中轉,具體表現是:

          通信原理

          上面說到提供了渲染層與Native、Native與邏輯層之間消息通訊的機制。機制是機制,具體的通信手段又是什么呢?

          這層通信機制在iOS和安卓系統的實現方式并不一樣,iOS是利用了的提供特性,而在安卓則是往WebView的window對象中注入一個原生方法,最終會封裝成這樣一個兼容層。

          (在微信開發者工具中則是使用了進行了封裝,詳情見)

          微信開發者工具雙線程通信的設計

          回到上上文中,我們提到線程的通信是通過Native做中轉,我們知道Native理論上是微信客戶端,但是對于微信開發者工具而言,它并不是微信客戶端,沒有Native。那么它是怎么實現渲染層和邏輯層之間的通信的呢?是的,它是使用來完成線程間通信。

          在這里插入圖片描述

          微信開發者工具有一個消息中心底層模塊維持著一個服務器,小程序邏輯層的WebView和渲染層的WebView通過與開發者工具底層建立長連,使用的字段來區分Socket的來源。

          // 通過userAgent中獲取開發者工具WebSocket服務器監聽的端口
          const port = window.navigator.userAgent.match(/port\/(\d*)/)[1];
          // 通過指定 protocol == 'APPSERVICE' 告知開發者工具這個鏈接是來自邏輯層
          const ws = new WebSocket(`ws://127.0.0.1:${port}`, 'APPSERVICE');
          ws.onmessage = (evt) => {
            let msg = JSON.parse(evt.data);
            // 處理來自開發者工具的信息
          }
          // 調用API接口 wx.navigateBack
          ws.send(JSON.stringify({
            command: 'APPSERVICE_INVOKE',
            data: {
               api: 'navigateBack',
               args: {}
            }
          }))
          

          前面提到,Native通過分別在渲染層和邏輯層注入來實現二者與Native的通信,然后Native可以根據情況進行處理或者繼續向指定線程傳遞消息。為了保持與真實環境的一致,微信開發者工具沒有新增或者刪除的方法,只是在的基礎上進行了方法的重構。以下是部分源碼:

          微信小程序系統架構_微信小程序是什么架構_微信小程序架構

          window.WeixinJSBridge = {
            on: c,
            invoke: e,
            publish: t,
            subscribe: o,
          }
          

          可以說小程序雙線程通信離不開提供的上面的四個方法,下面淺淺介紹下這四個方法:

          on

          主要用來收集小程序開發者工具觸發的事件回調。

          當小程序開發者工具要觸發渲染層的某個動作時,借助服務向渲染層發送command: 命令,表示這個命令是來自開發者工具的,通過來告訴渲染層執行什么事件方法。

          invoke

          在小程序開發者工具中,以api的方式調用開發者工具提供的基礎能力,并提供對應api執行后的回調

          渲染層統一向服務發送command: 的命令,根據參數中的api值來確定調用開發者工具具體的api方法。

          調用完畢后,服務向渲染層發送command: ACK的命令,渲染層根據此標識知道api調用完畢,然后執行對應的回調

          publish

          主要用來向邏輯層發送信息,也就是說要調用邏輯層的事件方法

          該過程涉及到雙線程的通信,渲染層通過服務觸發邏輯層對應的事件方法。

          需要強調的是:publish沒有收集執行的回調,只用來通知邏輯層調用指定的方法,至于執不執行以及執行結果,渲染層并不關注。

          渲染層統一向服務發送command: 的命令,服務接到命令就向邏輯層轉發消息

          邏輯層收到消息后,根據消息參數的值確定具體調用哪一個方法

          主要用來收集邏輯層觸發的事件回調,和publish配套,就像中的發布訂閱模式。

          渲染層通過注冊事件方法,事件方法是邏輯層在某個時間段通知要執行。

          渲染層執行回調的時機是收到來自服務的command: 命令,通過來確定要執行具體什么事件方法

          最后

          第一天結束辣!蕪湖!

          淺淺介紹了一下小程序的誕生史,比較了小程序開發與傳統web開發的區別,引出了小程序的雙線程架構。

          中間也多次提到了雙線程機制的好處,然鵝不得不說的是雖然雙線程機制相比web技術對于小程序來說更加安全,性能也有明顯的提升,但也并不是十全十美的。

          web技術可以在線即時更新,而這種雙線程機制必須將代碼打包提交到微信官方進行審核后才能發布,這也限制了開發者的自由度。并且JsCore沒有一個完整的瀏覽器對象,無法使用DOM API和BOM API,導致一些我們常用的js庫就失去了用武之地。

          這告訴我們:技術與架構本身就沒有好壞之分,每一種技術的發布,其目的都在為開發提供多元化的方式,理性看待,孰優孰劣還需要結合自身的應用環境。

          淺淺期待一下學習前端的第二天叭(?????)

          參考文章:


          主站蜘蛛池模板: 精品视频一区二区三区四区| 女人和拘做受全程看视频日本综合a一区二区视频 | 国产一区二区免费在线| 久久国产精品一区二区| 一区二区三区在线看| 久久中文字幕无码一区二区| 久久人做人爽一区二区三区| 国产精品美女一区二区视频| 久久精品一区二区影院| 超清无码一区二区三区| 亚州国产AV一区二区三区伊在| 美女视频一区二区| 国产三级一区二区三区| 日韩视频免费一区二区三区| 亚洲AV无码国产精品永久一区| 国产午夜精品片一区二区三区| AA区一区二区三无码精片| 亚洲中文字幕一区精品自拍 | 国产丝袜一区二区三区在线观看| 性盈盈影院免费视频观看在线一区| 亚洲一区免费视频| 亚洲av日韩综合一区久热| 日韩一区二区a片免费观看| 久热国产精品视频一区二区三区| 日韩精品国产一区| 精品一区二区高清在线观看| chinese国产一区二区| 不卡一区二区在线| 香蕉免费一区二区三区| 亚洲一区二区三区久久| AV鲁丝一区鲁丝二区鲁丝三区| 亚洲无码一区二区三区| 国产精品免费综合一区视频| 无码日韩人妻AV一区二区三区| 中文字幕无码一区二区三区本日| 亚洲国产一区在线| 日韩中文字幕一区| 免费在线视频一区| 国产成人精品一区二区秒拍| 波多野结衣一区二区| 日本高清无卡码一区二区久久|