本篇文章為大家帶來了關於微信小程式的相關問題,其中主要介紹了關於基礎架構原理的相關內容,其中包括了宿主環境、執行環境、小程式整體架構、運作機制、更新機制、數據通訊機制等等內容,下面一起來看一下,希望對大家有幫助。
【相關學習推薦:小程式學習教學】
下圖為微信小程式的整體架構圖:
我們先來簡單講講微信小程式的發展歷,知己知彼方能百戰不殆。微信小程式簡稱小程式。張小龍於2017年01月09日在微信公開課上宣布正式上線。小程式英文名為 Mini Program,是一種不需要下載安裝即可使用的應用,它實現了應用程式「觸手可及」的夢想,用戶掃一掃或搜尋即可開啟應用程式。
小程式上線以來,一直被稱為便攜版的 APP,關於兩者之間的區別,無外乎是小程式相對輕巧、開發成本低、開發週期短、收效快。
小程式並非憑空冒出來的一個概念,當微信中的 WebView 逐漸成為行動 Web 的一個重要入口時,微信就有相關的 JS API 了。
WebView 是行動端(手機、IPad)提供的運行JavaScript 的環境,是系統渲染Web 網頁的一個控件,可與頁面JavaScript 交互,實現APP 與Web 的混合開發,WebView 渲染Web 頁面需要強大的渲染核心支持,這其中Android 與IOS 系統的核心又有所不一樣。
根據了解,小程式誕生的背景主要推動力是由於行動網頁在微信內傳播體驗不良,能力不強,當然我覺得這其中也有原生APP 缺點原因的推動,例如每次都要從App Store 或其他應用程式市場下載,即使下載了,也佔據系統很大的空間,如果不常用,被使用者刪掉的可能性也非常大。
我們先拋開原生APP的問題不談,對於行動網頁在微信內傳播體驗不良,能力不強的問題,即使後來微信團隊推出了JS-SDK 來解決行動網頁能力不足的問題,但JS-SDK 的模式並沒有解決使用行動網頁遇到的體驗不良的問題,這其中的原因大概能概括為這三個點:白屏問題、頁面切換的生硬和點擊的遲滯感。
為了解決這些問題,微信團隊面臨的問題是如何設計一個比較好的系統,使得所有開發者在微信中都能獲得比較好的體驗。這個問題是之前的 JS-SDK 所處理不了的,需要一個全新的系統來完成,它需要讓所有的開發者都能做到:
快速的載入。
更強大的能力。
原生的體驗。
易用且安全的微信資料開放。
有效率且簡單的開發。
這就是小程式的由來。文件
微信小程式的宿主環境為微信客戶端,它是依賴微信客戶端上執行的,並且跟小程式 基礎庫 版本有重大關聯關係。
我們可以把 微信客戶端 以及 小程式基礎庫 簡稱為微信小程式的宿主環境。
微信小程式可以呼叫宿主環境提供的微信客戶端的能力,可以完成許多普通網頁無法完成的功能,這使得小程式比普通網頁擁有更多的能力。小程式會運行在不同版本(不同的微信客戶端 不同基礎庫)的宿主環境下,因此針對各個版本的宿主環境做程式上的相容也是在所難免的。
小程式的主要開發語言是Javascript,它與傳統網頁開發具有相似性但還是有一定區別:
網頁開發,渲染執行緒和腳本是互斥的,這也是為什麼長時間的腳本運行可能會導致頁面失去回應的原因,本質就是我們常說的JS 是單執行緒的。
小程序,視圖層和邏輯層是分開的,雙執行緒同時運行,視圖層的介面使用 WebView 進行渲染,邏輯層運行在 JSCore 中。
網頁開發,主要面對各廠商的瀏覽器,在行動端還需要面對 Safari、Chrome 以及 iOS、Android 系統中的各式 WebView。
小程序,主要面對兩大作業系統IOS和Android的微信客戶端,還有開發工具、PC端(window)、Mac。開發時候要注意的是微信客戶端的版本號碼和小程式API 支援的基礎函式庫版本號。
微信小程式運行在多種平台上:iOS(iPhone/iPad)微信客戶端、Android 微信客戶端、PC 微信客戶端、Mac 微信客戶端和用於調試的微信開發者工具。
各平台腳本執行環境以及用於渲染非原生元件的環境是各不相同的,具體區別如下:
透過上面的內容,你應該大致了解小程式誕生的情況和所處的環境了,下面我們就來聊聊小程式的整體設計架構情況。
整個小程式系統架構分成兩個部分:視圖層(WebView) 和 邏輯層(App Service),這兩個部分分別由兩個獨立執行緒管理。
視圖層:也稱為渲染層,渲染層用來渲染頁面結構,主要由WebView 進行渲染,一個小程式可以存在多個介面,所以渲染層可能存在很多個WebView 線程。
邏輯層:邏輯層採用 JSCore 執行緒執行 JS 腳本。邏輯層主要用來邏輯處理、資料請求、介面呼叫等。
視圖層和邏輯層之間的溝通則需要藉助系統層(WeixinJsBridage) 進行通信,邏輯層把資料變化通知到視圖層,觸發視圖層頁面更新,視圖層把觸發的事件通知到邏輯層進行業務邏輯處理。
頁面渲染大致過程為:我們把專案進行編譯會把WXML 轉換成對應的JS 物件(Virtual DOM),在邏輯層發生資料變化的時候,我們會透過setData() 方法把資料從邏輯層傳遞到視圖層,視圖層接收到資料後,會內部進行差異對比,把差異應用在原來的Dom 樹上,再正確的渲染出UI 介面,完成頁面的渲染過程。
透過上面的分析,你是否能理解開頭放置的架構圖了
上面的分析也提及到了一個系統層(WeixinJsBridage),一般簡稱為JSBridge,它起到了一個中間橋樑的作用,非常重要。它不僅讓視圖層與邏輯層兩個單獨執行緒能進行通信,也架起上層開發與系統底層功能(Native)的橋樑,使得小程式可以透過呼叫API 使用原生功能,且部分元件用原生元件實現,從而有良好體驗。
邏輯層還有一個重要的操作,發送網路請求,它也是經由 系統層 轉送的。
講到這裡,希望你對小程式的整體架構有一定認識了,下面我們就開始講一下小程式內部的一些機制狀況了。
小程式啟動運行兩種情況:
#冷啟動(重新開始):使用者首次開啟或小程式被微信主動銷毀後再次開啟的情況,此時小程式需要重新載入啟動,即為冷啟動。
熱啟動:用戶已經打開過小程序,然後在一定時間內再次打開該小程序,此時無需重新啟動,只需要將後台態的小程序切換到前台,這個過程就是熱啟動。
要注意:
1.小程式沒有重新啟動的概念。
2.當小程式進入後台,客戶端會維持一段時間的運作狀態,超過一定時間後會被微信主動銷毀。
3.短時間內收到系統兩次以上記憶體警告,也會對小程式進行銷毀,這也就為什麼一旦頁面記憶體溢出,頁面會奔潰的本質原因了。
小程式冷啟動時如果發現有新版本,將會異步下載新版本的包,並同時會先用客戶端本地的舊包進行啟動,等下次冷啟動才會應用上。如果需要馬上套用最新版本,可以用 wx.getUpdateManager API 來處理。
const updateManager = wx.getUpdateManager() updateManager.onCheckForUpdate(function (res) { // 请求完新版本信息的回调 console.log(res.hasUpdate) }) updateManager.onUpdateReady(function () { wx.showModal({ title: '更新提示', content: '新版本已经准备好,是否重启应用?', success(res) { if (res.confirm) { // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 updateManager.applyUpdate() } } }) }) updateManager.onUpdateFailed(function () { // 新版本下载失败 })
前面我們講過小程式是基於雙執行緒的,那就意味著任何在視圖層和邏輯層之間的資料傳遞都是線程間的通信,也就是會有一定的延遲。這不像傳統Web一樣,當頁面要更新時呼叫相關API就能同步渲染出來,在小程式架構裡面,這一切成了非同步操作。
非同步會使得各部分的運行時序變得複雜一些。例如在渲染首屏的時候,邏輯層與渲染層會同時開始初始化工作,但是渲染層需要有邏輯層的資料才能把介面渲染出來,如果渲染層初始化工作較快完成,就要等邏輯層的指令才能進行下一步工作。因此邏輯層與渲染層需要有一定的機制保證時序正確,在每個小程式頁面的生命週期中,存在著若干次頁面資料通訊。
知道視圖層與邏輯層的具體通訊過程後,我們也稍微了解一下視圖層和邏輯層的資料傳輸大致是如何的,我們知道這兩者通訊是藉助了系統層的作用,而實際上是透過兩邊提供的evaluateJavascript 所實現的。也就是使用者傳輸的數據,需要將其轉換為字串形式傳遞,同時把轉換後的數據內容拼接成一份 JS 腳本,再透過執行 JS 腳本的形式傳遞到兩邊獨立環境。
關於evaluateJavascript:
Native 呼叫 JS, 一般就是直接 JS 程式碼字串,有點類似我們呼叫 JS 中的 eval 去執行一串程式碼。它一般有 loadUrl、evaluateJavascript 等幾種方法。
這裡就不做過多的介紹了,你只要記住,它是用來呼叫執行 JS 字串,是一種 Native 用來識別 JS 程式碼的方式的就行啦。
做過小程式的鐵汁們應該對這張圖不陌生了:
圖中過程主要是為了獲得微信使用者的唯一openid 與session_key,之後開發者伺服器可以根據使用者識別來產生自訂登入態,用於後續業務邏輯中前後端互動時識別使用者身分。
呼叫 wx.login() 取得暫時登入憑證 code,並回傳到開發者伺服器。
調用auth.code2Session 接口,換取用戶唯一標識openid 、用戶在微信開放平台帳號下的唯一標識UnionID(若當前小程式已綁定到微信開放平台帳號)和會話金鑰session_key。
UnionID 是微信不久前新增加的一個性質,其獲取方式和openid 差不多,作用也差不多,都是指用戶唯一標識,但它的範圍廣一點。
官方解釋:如果開發者擁有多個行動應用程式、網站應用程式、和公用帳號(包括小程式),可透過UnionID 來區分使用者的唯一性,因為只要是同一個微信開放平台帳號下的行動應用程式、網站應用程式和公眾帳號(包括小程式),使用者的UnionID 是唯一的。換句話說,同一用戶,對同一個微信開放平台下的不同應用,UnionID是相同的。
不明白?說穿了,就是把小程式綁定 微信開放平台帳號 後,可與該帳號下綁定的的其他行動應用程式、網站應用程式及公眾號打通。例如:同個用戶在PC端的掃描登錄、微信公眾號開發的頁面授權登錄、微信小程式授權登錄,這些場景中都能辨識出是同一個用戶,取得到的 UnionID 相同的。傳送門
透過學習了小程式的架構原理,我們再來用底層架構的眼光來簡單分析一下常見的小程式效能問題是如何產生的。
頻繁地呼叫setData()
頻繁地呼叫setData(),這個問題相信已經是很常見的,例如在計時器中調用、在監聽頁面滾動的鉤子中調用,這些場景很容易就會引起小程式的效能問題,容易出現頁面卡頓、頁面資料更新不及時的情況。
前面在資料通訊機制中我們講過小程式是基於雙線程的,那就意味著任何在視圖層和邏輯層之間的資料傳遞都是線程間的通信,頻繁的去調用setData(),會使得執行緒之間一直處於忙碌狀態,邏輯層通知到視圖層耗時就會上升,視圖層收到訊息的時候可能已經距離發出的時間超過一定時間了,渲染頁面就不夠及時了。
龐大的資料量去呼叫setData()
#還是在前面的資料通訊機制中,我們說過傳輸的資料需要轉換成轉換為字串的形式傳遞,且透過JS 腳本的形式去執行,當資料量大時,執行腳本的編譯執行時間也會上漲,佔用執行緒。
頁面複雜繁多的DOM結構
當一個頁面DOM 結構複雜且非常多的時候,這必定帶來頁面顯示不及時,頁面卡頓,甚至可能會出現頁面奔潰的情況,這其中的原因可想而知,是過於DOM 繪製、計算都是需要時間的,這將使得線程過渡的工作,帶來客戶端內存佔用上升,從而觸發系統回收小程式頁面。
上面我提到說,對「邏輯層運行在JSCore 中」 這句話有點疑問,是因為我在看到表格中列舉的邏輯層運行的環境應該是依照系統環境區分的才對,那這句話是不是就太籠統了?還是說這句話是指 IOS 的情況呢?因為是官方文件寫的話語,所以我沒有直接就否決是寫錯了,或是單指IOS 的情況。
經過一翻查證,證實其實這句話是沒有問題的,要追尋結果的過程,我們需要寫了解一下瀏覽器的大致情況:
瀏覽器中最核心的部分則是瀏覽器內核,每個瀏覽器都有各自的內核,而對行動領域影響最深的則當屬WebKit。
WebKit 就是一個頁面渲染以及邏輯處理引擎,HTML/CSS/JavaScript 經過它的處理,成為可見且可操作的Web頁面。
WebKit 由多個重要模組組成,整體架構如下圖:
#WebKit 由四個部分組成,分別是:
WebKit Embedding API:負責瀏覽器UI 與WebKit 互動的部分。
Platform API(WebKit Ports):讓 Webkit 更方便的移植到各個作業系統、平台上,提供的一些呼叫Native Library的介面。
WebCore:整個 WebKit 中最核心的渲染引擎。
JavascriptCore:JSCore 是 WebKit 預設內嵌的JS引擎,由蘋果使用 C 開發。
我們來專注於JSCore 部分,JSCore 是WebKit 預設內嵌的JS引擎,之所以說是預設內嵌,是因為許多基於WebKit 分支開發的瀏覽器引擎都開發了自家的JS引擎,其中最有名的就是Chrome的V8 引擎。
V8 引擎,相信前端的小夥伴應該不會很陌生了,既然它是基於 WebKit 的,那底層預設也是內嵌 JSCore 的,而 Android 的邏輯層是運行在 V8 上的。
而 IOS 的瀏覽器引擎則是 WebKit,內部則是 JSCore。
最後開發工具的邏輯層是運行在NW.js, 上它的官網,看到怎麼一段話:
##我相信它應該也和 WebKit 扯上關係了。 【相關學習推薦:小程式學習教學】
以上是微信小程式架構原理基礎詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!