溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

小程序運行機制的示例分析

發(fā)布時間:2021-04-01 10:40:57 來源:億速云 閱讀:129 作者:小新 欄目:移動開發(fā)

小編給大家分享一下小程序運行機制的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

寫作背景

接觸小程序有一段時間了,總得來說小程序開發(fā)門檻比較低,但其中基本的運行機制和原理還是要懂的?!氨热缥以诿嬖嚨臅r候問到一個關(guān)于小程序的問題,問小程序有window對象嗎?他說有吧”,但其實是沒有的。感覺他并沒有了解小程序底層的一些東西,歸根結(jié)底來說應(yīng)該只能算會使用這個工具,但并不明白其中的道理。

小程序與普通網(wǎng)頁開發(fā)是有很大差別的,這就要從它的技術(shù)架構(gòu)底層去剖析了。還有比如習(xí)慣Vue,react開發(fā)的開發(fā)者會吐槽小程序新建頁面的繁瑣,page必須由多個文件組成、組件化支持不完善、每次更改 data 里的數(shù)據(jù)都得setData、沒有像Vue方便的watch監(jiān)聽、不能操作Dom,對于復(fù)雜性場景不太好,之前不支持npm,不支持sass,less預(yù)編譯處理語言。

“有的人說小程序就像被閹割的Vue”,哈哈當然了,他們從設(shè)計的出發(fā)點就不同,咱也得理解小程序設(shè)計的初衷,通過它的使用場景,它為什么采用這種技術(shù)架構(gòu),這種技術(shù)架構(gòu)有什么好處,相信在你了解完這些之后,就會理解了。下面我會從以下幾個角度去分析小程序的運行機制和它的整體技術(shù)架構(gòu)。

了解小程序的由來

在小程序沒有出來之前,最初微信WebView逐漸成為移動web重要入口,微信發(fā)布了一整套網(wǎng)頁開發(fā)工具包,稱之為 JS-SDK,給所有的 Web 開發(fā)者打開了一扇全新的窗戶,讓所有開發(fā)者都可以使用到微信的原生能力,去完成一些之前做不到或者難以做到的事情。

但JS-SDK 的模式并沒有解決使用移動網(wǎng)頁遇到的體驗不良的問題,比如受限于設(shè)備性能和網(wǎng)絡(luò)速度,會出現(xiàn)白屏的可能。因此又設(shè)計了一個增強版JS-SDK,也就是“微信 Web 資源離線存儲”,但在復(fù)雜的頁面上依然會出現(xiàn)白屏的問題,原因表現(xiàn)在頁面切換的生硬和點擊的遲滯感。這個時候需要一個 JS-SDK 所處理不了的,使用戶體驗更好的一個系統(tǒng),小程序應(yīng)運而生。

快速的加載

更強大的能力

原生的體驗

易用且安全的微信數(shù)據(jù)開放

高效和簡單的開發(fā)

小程序與普通網(wǎng)頁開發(fā)的區(qū)別

小程序的開發(fā)同普通的網(wǎng)頁開發(fā)相比有很大的相似性,小程序的主要開發(fā)語言也是 JavaScript,但是二者還是有些差別的。

普通網(wǎng)頁開發(fā)可以使用各種瀏覽器提供的 DOM API,進行 DOM 操作,小程序的邏輯層和渲染層是分開的,邏輯層運行在 JSCore 中,并沒有一個完整瀏覽器對象,因而缺少相關(guān)的DOM API和BOM API。

普通網(wǎng)頁開發(fā)渲染線程和腳本線程是互斥的,這也是為什么長時間的腳本運行可能會導(dǎo)致頁面失去響應(yīng),而在小程序中,二者是分開的,分別運行在不同的線程中。

網(wǎng)頁開發(fā)者在開發(fā)網(wǎng)頁的時候,只需要使用到瀏覽器,并且搭配上一些輔助工具或者編輯器即可。小程序的開發(fā)則有所不同,需要經(jīng)過申請小程序帳號、安裝小程序開發(fā)者工具、配置項目等等過程方可完成。

小程序的執(zhí)行環(huán)境

小程序架構(gòu)

一、技術(shù)選型

一般來說,渲染界面的技術(shù)有三種:

用純客戶端原生技術(shù)來渲染

用純 Web 技術(shù)來渲染

用客戶端原生技術(shù)與 Web 技術(shù)結(jié)合的混合技術(shù)(簡稱 Hybrid 技術(shù))來渲染

通過以下幾個方面分析,小程序采用哪種技術(shù)方案

開發(fā)門檻:Web 門檻低,Native 也有像 RN 這樣的框架支持

體驗:Native 體驗比 Web 要好太多,Hybrid 在一定程度上比 Web 接近原生體驗

版本更新:Web 支持在線更新,Native 則需要打包到微信一起審核發(fā)布

管控和安全:Web 可跳轉(zhuǎn)或是改變頁面內(nèi)容,存在一些不可控因素和安全風(fēng)險

由于小程序的宿主環(huán)境是微信,如果用純客戶端原生技術(shù)來編寫小程序,那么小程序代碼每次都需要與微信代碼一起發(fā)版,這種方式肯定是不行的。

所以需要像web技術(shù)那樣,有一份隨時可更新的資源包放在云端,通過下載到本地,動態(tài)執(zhí)行后即可渲染出界面。如果用純web技術(shù)來渲染小程序,在一些復(fù)雜的交互上可能會面臨一些性能問題,這是因為在web技術(shù)中,UI渲染跟JavaScript的腳本執(zhí)行都在一個單線程中執(zhí)行,這就容易導(dǎo)致一些邏輯任務(wù)搶占UI渲染的資源。

所以最終采用了兩者結(jié)合起來的Hybrid 技術(shù)來渲染小程序,可以用一種近似web的方式來開發(fā),并且可以實現(xiàn)在線更新代碼,同時引入組件也有以下好處:

擴展 Web 的能力。比如像輸入框組件(input, textarea)有更好地控制鍵盤的能力

體驗更好,同時也減輕 WebView 的渲染工作

繞過 setData、數(shù)據(jù)通信和重渲染流程,使渲染性能更好

用客戶端原生渲染內(nèi)置一些復(fù)雜組件,可以提供更好的性能

二、雙線程模型

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

那么為什么要這樣設(shè)計呢,前面也提到了管控和安全,為了解決這些問題,我們需要阻止開發(fā)者使用一些,例如瀏覽器的window對象,跳轉(zhuǎn)頁面、操作DOM、動態(tài)執(zhí)行腳本的開放性接口。

我們可以使用客戶端系統(tǒng)的 JavaScript 引擎,iOS 下的 JavaScriptCore 框架,安卓下騰訊 x5 內(nèi)核提供的 JsCore 環(huán)境。

這個沙箱環(huán)境只提供純 JavaScript 的解釋執(zhí)行環(huán)境,沒有任何瀏覽器相關(guān)接口。

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

邏輯層:創(chuàng)建一個單獨的線程去執(zhí)行 JavaScript,在這里執(zhí)行的都是有關(guān)小程序業(yè)務(wù)邏輯的代碼,負責(zé)邏輯處理、數(shù)據(jù)請求、接口調(diào)用等

視圖層:界面渲染相關(guān)的任務(wù)全都在 WebView 線程里執(zhí)行,通過邏輯層代碼去控制渲染哪些界面。一個小程序存在多個界面,所以視圖層存在多個 WebView 線程

JSBridge 起到架起上層開發(fā)與Native(系統(tǒng)層)的橋梁,使得小程序可通過API使用原生的功能,且部分組件為原生組件實現(xiàn),從而有良好體驗

三、雙線程通信

把開發(fā)者的 JS 邏輯代碼放到單獨的線程去運行,但在 Webview 線程里,開發(fā)者就沒法直接操作 DOM。

那要怎么去實現(xiàn)動態(tài)更改界面呢?

如上圖所示,邏輯層和試圖層的通信會由 Native (微信客戶端)做中轉(zhuǎn),邏輯層發(fā)送網(wǎng)絡(luò)請求也經(jīng)由 Native 轉(zhuǎn)發(fā)。

這也就是說,我們可以把 DOM 的更新通過簡單的數(shù)據(jù)通信來實現(xiàn)。

Virtual DOM 相信大家都已有了解,大概是這么個過程:用 JS 對象模擬 DOM 樹 -> 比較兩棵虛擬 DOM 樹的差異 -> 把差異應(yīng)用到真正的 DOM 樹上。

如圖所示:

在渲染層把 WXML 轉(zhuǎn)化成對應(yīng)的 JS 對象。

在邏輯層發(fā)生數(shù)據(jù)變更的時候,通過宿主環(huán)境提供的 setData 方法把數(shù)據(jù)從邏輯層傳遞到 Native,再轉(zhuǎn)發(fā)到渲染層。

經(jīng)過對比前后差異,把差異應(yīng)用在原來的 DOM 樹上,更新界面。

我們通過把 WXML 轉(zhuǎn)化為數(shù)據(jù),通過 Native 進行轉(zhuǎn)發(fā),來實現(xiàn)邏輯層和渲染層的交互和通信。

而這樣一個完整的框架,離不開小程序的基礎(chǔ)庫。

四、小程序的基礎(chǔ)庫

小程序的基礎(chǔ)庫可以被注入到視圖層和邏輯層運行,主要用于以下幾個方面:

在視圖層,提供各類組件來組建界面的元素

在邏輯層,提供各類 API 來處理各種邏輯

處理數(shù)據(jù)綁定、組件系統(tǒng)、事件系統(tǒng)、通信系統(tǒng)等一系列框架邏輯

由于小程序的渲染層和邏輯層是兩個線程管理,兩個線程各自注入了基礎(chǔ)庫。

小程序的基礎(chǔ)庫不會被打包在某個小程序的代碼包里邊,它會被提前內(nèi)置在微信客戶端。

這樣可以:

降低業(yè)務(wù)小程序的代碼包大小

可以單獨修復(fù)基礎(chǔ)庫中的 Bug,無需修改到業(yè)務(wù)小程序的代碼包

五、Exparser 框架

Exparser是微信小程序的組件組織框架,內(nèi)置在小程序基礎(chǔ)庫中,為小程序的各種組件提供基礎(chǔ)的支持。小程序內(nèi)的所有組件,包括內(nèi)置組件和自定義組件,都由Exparser組織管理。

Exparser的主要特點包括以下幾點:

基于Shadow DOM模型:模型上與WebComponents的ShadowDOM高度相似,但不依賴瀏覽器的原生支持,也沒有其他依賴庫;實現(xiàn)時,還針對性地增加了其他API以支持小程序組件編程。

可在純JS環(huán)境中運行:這意味著邏輯層也具有一定的組件樹組織能力。

高效輕量:性能表現(xiàn)好,在組件實例極多的環(huán)境下表現(xiàn)尤其優(yōu)異,同時代碼尺寸也較小。

小程序中,所有節(jié)點樹相關(guān)的操作都依賴于Exparser,包括WXML到頁面最終節(jié)點樹的構(gòu)建、createSelectorQuery調(diào)用和自定義組件特性等。

內(nèi)置組件

基于Exparser框架,小程序內(nèi)置了一套組件,提供了視圖容器類、表單類、導(dǎo)航類、媒體類、開放類等幾十種組件。有了這么豐富的組件,再配合WXSS,可以搭建出任何效果的界面。在功能層面上,也滿足絕大部分需求。

六、運行機制

小程序啟動會有兩種情況,一種是「冷啟動」,一種是「熱啟動」。假如用戶已經(jīng)打開過某小程序,然后在一定時間內(nèi)再次打開該小程序,此時無需重新啟動,只需將后臺狀態(tài)的小程序切換到前臺,這個過程就是熱啟動;冷啟動指的是用戶首次打開或小程序被微信主動銷毀后再次打開的情況,此時小程序需要重新加載啟動。

小程序沒有重啟的概念

當小程序進入后臺,客戶端會維持一段時間的運行狀態(tài),超過一定時間后(目前是5分鐘)會被微信主動銷毀

當短時間內(nèi)(5s)連續(xù)收到兩次以上收到系統(tǒng)內(nèi)存告警,會進行小程序的銷毀

七、更新機制

小程序冷啟動時如果發(fā)現(xiàn)有新版本,將會異步下載新版本的代碼包,并同時用客戶端本地的包進行啟動,即新版本的小程序需要等下一次冷啟動才會應(yīng)用上。 如果需要馬上應(yīng)用最新版本,可以使用 wx.getUpdateManager API 進行處理。

八、性能優(yōu)化

主要的優(yōu)化策略可以歸納為三點:

精簡代碼,降低WXML結(jié)構(gòu)和JS代碼的復(fù)雜性;

合理使用setData調(diào)用,減少setData次數(shù)和數(shù)據(jù)量;

必要時使用分包優(yōu)化。

1、setData 工作原理

小程序的視圖層目前使用 WebView 作為渲染載體,而邏輯層是由獨立的 JavascriptCore 作為運行環(huán)境。在架構(gòu)上,WebView 和 JavascriptCore 都是獨立的模塊,并不具備數(shù)據(jù)直接共享的通道。當前,視圖層和邏輯層的數(shù)據(jù)傳輸,實際上通過兩邊提供的 evaluateJavascript 所實現(xiàn)。即用戶傳輸?shù)臄?shù)據(jù),需要將其轉(zhuǎn)換為字符串形式傳遞,同時把轉(zhuǎn)換后的數(shù)據(jù)內(nèi)容拼接成一份 JS 腳本,再通過執(zhí)行 JS 腳本的形式傳遞到兩邊獨立環(huán)境。

而 evaluateJavascript 的執(zhí)行會受很多方面的影響,數(shù)據(jù)到達視圖層并不是實時的。

2、常見的 setData 操作錯誤

頻繁的去 setData在我們分析過的一些案例里,部分小程序會非常頻繁(毫秒級)的去setData,其導(dǎo)致了兩個后果:Android下用戶在滑動時會感覺到卡頓,操作反饋延遲嚴重,因為 JS 線程一直在編譯執(zhí)行渲染,未能及時將用戶操作事件傳遞到邏輯層,邏輯層亦無法及時將操作處理結(jié)果及時傳遞到視圖層;渲染有出現(xiàn)延時,由于 WebView 的 JS 線程一直處于忙碌狀態(tài),邏輯層到頁面層的通信耗時上升,視圖層收到的數(shù)據(jù)消息時距離發(fā)出時間已經(jīng)過去了幾百毫秒,渲染的結(jié)果并不實時;

每次 setData 都傳遞大量新數(shù)據(jù)由setData的底層實現(xiàn)可知,我們的數(shù)據(jù)傳輸實際是一次 evaluateJavascript

腳本過程,當數(shù)據(jù)量過大時會增加腳本的編譯執(zhí)行時間,占用 WebView JS 線程, 后臺態(tài)頁面進行 setData當頁面進入后臺態(tài)(用戶不可見),不應(yīng)該繼續(xù)去進行setData,后臺態(tài)頁面的渲染用戶是無法感受的,另外后臺態(tài)頁面去setData也會搶占前臺頁面的執(zhí)行。

以上是“小程序運行機制的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI