小程序底層架構
與瀏覽器對比
以微信小程序爲例,與瀏覽器中的對應關係:
- js 開發邏輯代碼 -> js -> v8
- wxss (多了rpx單位)控制樣式 -> css -> 瀏覽器渲染器
- wxml xml語言 控制渲染層展示 -> html -> 瀏覽器渲染器 -> dom
瀏覽器
- 單線程 存在阻塞
小程序
- 雙線程架構
- js 邏輯層
- wxml、wxss 視圖層
- JSBridge 通信(可以實現相機、掃碼)
微信小程序初級架構
- 所有的邏輯代碼會打成一份,一個小程序只有一個邏輯層,包含所有頁面邏輯 js
- 視圖層(渲染層)一個頁面對應一個
Webview
,小程序中頁面棧最多十層。- webview 用來渲染 wxml 和 wxss
- 在本地開發工具,直接用 iframe
- 在客戶端,用真的 webview
- webview 用來渲染 wxml 和 wxss
小程序運行環境
運行環境 | 邏輯層 | 渲染層 |
---|---|---|
iOS | JavaScriptCore | WKWebView |
安卓 | V8 | chromium定製內核 |
小程序開發者工具 | NWJS | Chrome WebView |
nw:node(io/網絡/資源處理/js)-webkit(html/css)
底層實現(基礎庫)
基礎庫:對底層運行時的封裝,提供事件、數據變更、通信、基礎函數
底層需要實現的功能:
- 視圖層和邏輯層的編譯
- 邏輯層和視圖層之間的通信
查看基礎庫
微信開發工具 -> 執行 openVendor()
-> 打開基礎庫
可以看到兩個可執行文件:
- wcc: Wechat WXML Complier wxml 編譯器
- wcsc: Wechat WXSS Compiler wxss 編譯器
和基礎庫 xxx.wxvpkg
。
基礎庫內容
基礎庫用 wxappUnpacker 反編譯,得到:
- WAWebview.js 視圖層引擎
Foundation
基礎模塊- 提供環境變量 env、isService、isWebview、eventEmit、jsbridge、ready監聽 配置
WeixinJSBridge
消息通信機制NativeBuffer
轉換數據格式Reporter
日誌系統exparser
組件系統 Shadow DOM、WebComponent 規範、wx-element- 提供友好交互的組件 picker、slider、swiper 等
- 承接原生組件 video、canvas 等
- 事件系統
- 註冊組件
window.exparser.registerElement()
__virtualDOM__
- WAService.js 邏輯層引擎
Foundation
基礎模塊- 提供環境變量 env、isService、isWebview、eventEmit、jsbridge、ready監聽 配置
WeixinJSBridge
消息通信機制- 路由管理
- 生命週期管理
__subContextEngine
: App、Page、Component getApp__virtualDOM__
:提供querySelector
方法
編譯器
編譯 wxml
wcc(Wechat WXML Complier) wxml 編譯器 -> js
初始化時:
- 編譯生成 js,執行 js 生成構建虛擬 dom 的函數
- 數據傳遞給 構建虛擬 dom 的函數,生成 vdom 描述
- vdom 描述經過組件系統 exparser 的解析構建真實 dom
數據變更時:
- 執行上面 2、3 步
- dom diff 對比、渲染
wxml 經過 WAWebview 編譯成 js,js + 虛擬 dom -> wxml描述文件,交給組件系統 exparser,去渲染更新
編譯 wxss
wcsc(Wechat WXSS Compiler) wxss 編譯器 -> js
- 處理單位 rpx,根據手機物理像素及分辨率來計算實際應該爲多少
- 生成新的 style,插入
初始化流程
渲染層
控制檯輸入 document.getElementsByTag('webview')[0]
得到渲染層。
- 初始化
__webviewId__
(標識當前是哪個 webview )、__wxAppCode__
- wcc 生成渲染器方法的代碼(wxml -> js)
- 加載執行 wcsc 打包出來的代碼(js代碼),生成 css
- 初始化頁面配置
- $gwx -> generateFunc(渲染器,執行生成虛擬 Dom),需要數據
- 觸發自定義事件,傳遞渲染器函數
var generateFunc = $gwx(decodeName) if(generateFunc) { var CE = window.CustomEvent document.dispatchEvent(new CE('generateFuncReady', { detail: { generateFunc: generateFunc } })) } else { ... }
- 基礎庫
WAWebview
中監聽了generateFuncReady
事件,該事件中會觸發WexinJSBridge
,通知邏輯層渲染層已加載完成,等待邏輯層傳數據。邏輯層執行完之後執行generateFunc
回調,並拿到邏輯層傳來的數據,生成虛擬 dom - 虛擬 dom 描述經過組件系統 exparser 的解析構建真實 dom
邏輯層
控制檯輸入 document
得到邏輯層。
- 初始化配置項(頁面配置項、全局配置項)
- 加載邏輯層基礎庫(維護了 Page、App、Component、wx.getSetting、wx.scanCode 等)
- 維護一個邏輯層渲染器,加載邏輯代碼(開發者寫的代碼)
- 構建
__wxAppCode__
,保存所有頁面的配置和渲染器方法