WebView是屬于單線程模型,頁面的渲染和JavaScript邏輯運算都是運行在WebView中,而微信小程序是使用雙線程模式,就是渲染層和邏輯層分開。
渲染層和邏輯層
在微信的文檔可以看到這么一段話,小程序的渲染層和邏輯層分別由2個線程管理:渲染層的界面使用了WebView 進(jìn)行渲染;邏輯層采用JsCore線程運行JS腳本。一個小程序存在多個界面,所以渲染層存在多個WebView線程,這兩個線程的通信會經(jīng)由微信客戶端(下文中也會采用Native來代指微信客戶端)做中轉(zhuǎn),邏輯層發(fā)送網(wǎng)絡(luò)請求也經(jīng)由Native轉(zhuǎn)發(fā),小程序的通信模型下圖所示。

理解WebView的單線程模式
在理解雙線程模式前我們先來理解WebView的單線程模型,瀏覽器為每一個window分配一個線程用于執(zhí)行JavaScript,每一時刻只會有一段JS代碼在執(zhí)行,那么在JavaScript實現(xiàn)ajax網(wǎng)絡(luò)請求是不是異步的呢,雖然window是單線程,但是瀏覽器并不是單線程的,瀏覽器是基于事件驅(qū)動的,每一個window都有一個Event Loop,比如鼠標(biāo)點擊事件發(fā)生、定時器觸發(fā)事件、XMLHttpRequest 回調(diào)都會放入執(zhí)行隊列,隊列就會按照順序執(zhí)行事件,而其中的XMLHttpRequest網(wǎng)絡(luò)請求實際上是瀏覽器新開了一個線程執(zhí)行,把結(jié)果回調(diào)放入隊列。
小程序雙線程模式
WebView的邏輯運算和頁面渲染都是在同一個線程上,而微信小程序的渲染層還是運行在WebView,把JavaScript運行在JavaScript引擎,在Android是運行在V8引擎,而在iOS是運行在JavaScriptCore。
界面的渲染過程
WebView是使用HTML+CSS生成DOM,然后渲染到WebView,我們可以通過JS對DOM進(jìn)行操作,修改顯示的內(nèi)容。在微信小程序是使用wxml和wxss描述UI,和HTML、CSS的相對應(yīng)的,在邏輯層生成虛擬的DOM,然后發(fā)送到渲染層,渲染層會根據(jù)虛擬的DOM生成真實的DOM,渲染到WebView,但是為了提高性能,不會每一次都重新渲染,而且根據(jù)前后虛擬DOM的差異,把差異部分更新到真實的DOM,僅僅渲染這部分Diff。
<view>
Hello World
</view>
使用特定語言描述
{
"name":"view",
"children":[
{
"text":"Hello World"
}
]
}
為何使用雙線程模型
由于微信小程序定制了專用的DSL,HTML、CSS和JavaScript無法直接運行在小程序,由于使用了雙線程模式,也不能直接操作DOM,導(dǎo)致很多前端框架無法使用,這一點是被很多開發(fā)者所詬病。那么微信為何要這么設(shè)計呢?
使用專用的DSL,加上不允許操作DOM,邏輯和渲染都只能用程序包的代碼,意味著無法實現(xiàn)動態(tài)更新,對于平臺而已,開發(fā)者在小程序商店發(fā)布小程序是需要受到微信的監(jiān)控,發(fā)布的代碼也需要經(jīng)過自動審查,不允許開發(fā)者隨意更新代碼。
雙線程是否會提升性能?
把渲染層和邏輯層分別運行在不同的線程,多了一條線程貌似可以提升性能?實際上并不會,絕大多數(shù)的情況下,JS運行的片段耗時都是很短的,比如文件讀取、網(wǎng)絡(luò)請求等都是其它的線程進(jìn)行,并不會阻塞JS線程,然而UI的更新還需要跨線程發(fā)送到WebView中,這個顯然是會增加耗時,效率是更加低的。