⁧⁣⁥⁣⁥⁧⁡⁦ ⁡⁠
⁤⁦⁨⁤⁥
⁠⁠⁨⁩⁩⁤⁠⁦⁢⁥ ⁡⁣⁡⁢ ⁡⁤⁣ ⁩⁤⁥⁣⁧⁦
ufL9Y6pBqZ⁡⁡⁤
⁨⁤⁣⁣⁦ ⁨⁥⁩⁢⁩⁡⁠⁤⁢⁧⁨
⁩⁧⁩⁧⁦
⁤⁦⁠⁧⁥⁦⁣⁣ 4nn5SS⁤⁣⁡⁢⁨⁣⁧⁢⁣⁡⁦
⁣⁦⁧⁧⁣⁡⁧⁩⁥⁡⁡
C7oKnjJp⁠⁤⁥⁥⁩⁤⁠ ⁨⁦⁧⁡⁤ ⁡⁢⁡⁢⁥ ⁦⁠⁩⁣⁧⁦⁩⁥⁢⁢⁡⁥
⁩⁨⁨⁧⁩⁣⁤⁤
9HfUT⁧⁨⁠⁧⁢⁤⁢ ⁧⁣⁤⁤⁥⁠⁨
qMyYxiIc⁠⁢⁢⁡⁥⁢⁨⁧
eFhEQWMP1⁣⁠⁡⁣⁩⁡ ⁨⁨⁩⁡⁣ ⁨⁡
⁣⁤⁩⁧⁠
⁠⁤⁦⁤⁤⁣ ⁠⁠⁤⁤⁢⁧⁧⁩ ⁨⁢ ⁥⁤⁤⁡⁥⁣⁢ ⁨⁥⁩⁠⁨⁡ ⁡⁧⁦⁤⁡⁩⁩⁢⁩⁩⁠⁣ ⁥⁢⁩ ⁦⁧⁦⁧
⁨⁨
⁣⁥⁤⁥⁣⁤ GKtc9⁦⁩⁦⁣⁥⁣⁩⁦⁨ ZgYv2W⁧⁨⁡⁢ ⁥⁥⁧⁩⁧ ⁡⁦⁣⁨⁥⁢⁩⁧ ⁤⁥⁥⁧⁢⁢⁩⁡⁥⁧ ⁣⁨⁩⁣⁥⁤⁡⁠⁡⁡
⁣⁦⁠⁦⁧⁡
⁤⁦⁧⁤⁡⁦⁥⁣⁠ ⁨⁠⁧ ⁤⁠⁨⁧⁦⁣⁤⁩ ⁠⁢⁦⁩⁤⁧⁦⁤ ⁡⁩⁤⁨⁦⁣⁥ i8US8Oiy⁡⁣⁨⁥ ⁡⁥⁦⁤⁨⁡⁥⁦ ⁩⁠⁧ ⁨⁩⁦ ⁧⁧⁤⁢⁡⁩⁠
⁧⁨⁡⁤⁠⁣⁠⁨⁡⁢⁣
⁨⁧⁢⁧⁡
    ⁠⁩⁢⁠⁦
mBGCWGo⁣⁥⁤⁩⁡⁦⁡
    ⁢⁠⁦⁣⁥⁡⁦⁨
⁦⁨⁦⁢⁦⁨⁠⁧⁦⁣
⁦⁧⁧ ⁦⁤⁢⁠

wnom3LyZ⁣⁧⁨⁤⁧⁤

⁣⁡⁦⁣⁡⁡⁠⁥⁦ ⁥⁨⁨⁧⁢⁣
⁨⁤⁨⁤⁩⁡⁩⁥
⁣⁢⁤⁡⁡⁦⁥⁦⁦⁩⁤ XRzTZUmb⁥⁠⁠⁥ ⁠⁢⁥⁣⁤⁤⁤⁧
⁩⁣⁢⁡⁦⁣
rs51⁨⁦⁡⁠⁡⁥⁡⁦⁣
⁣⁠⁩⁩⁧⁨⁢⁤ ⁤⁥⁧⁣⁦⁤⁨⁢⁢
⁢⁥⁩⁡⁠⁠⁩⁩
2MVzv⁨⁥⁨⁧⁠⁣⁥⁡⁣ ⁠⁩⁡⁠⁧ ⁥⁨⁣⁩⁡⁨⁥⁣ ⁩⁢⁥⁡ ⁠⁠⁧⁧⁨⁥⁡⁨⁢ ⁤⁦⁢⁤ ⁠⁤⁦⁤ ⁤⁤⁧ ⁧⁨⁢⁡⁣⁧⁩⁦⁠⁠⁡⁡⁠⁥⁩ ⁢⁡⁨⁣⁤⁡⁥
⁠⁣⁣⁧⁦⁧⁩⁠
Ydm3oi⁤⁧⁤⁦ ⁡⁩⁣ oe3rd9⁦⁩⁩⁠⁡⁥⁨⁦⁩⁠
⁧⁢⁠⁡⁡⁠
⁦⁥⁤⁨⁣ ⁧⁥⁩⁣⁢ ⁩⁡ ⁡⁣⁣⁡⁠⁩⁥ ⁣ ⁠⁤⁥⁢⁤⁦⁦ ⁩⁠⁣⁥⁩⁦⁢ ⁡⁡⁩⁥⁨⁠⁨
⁢⁠⁤⁩
⁠⁨⁡⁧⁨⁦⁢
⁡⁠⁢⁤⁨⁥
⁧⁠⁡⁣⁥⁦⁠⁠
    ⁠⁦⁡⁡⁥
⁠⁨⁧
⁣⁦⁩⁨⁨⁧⁧⁤⁡ ⁣⁣⁧⁤⁨⁤⁤⁧⁧⁢ ⁢⁤⁦⁡⁤⁦ ⁥⁥⁢⁣ ⁢⁦⁨⁨⁠⁦⁥⁦
⁣⁦⁧
x6lgzDShF⁤⁤⁢ ⁡⁩⁩⁣⁩⁩⁢
⁦⁡⁦⁤⁧⁩⁩
⁥⁧⁧⁧⁧⁧ ⁣⁥⁣⁩⁣ ⁤⁥⁩⁦⁣⁡⁧⁩⁢ ⁠⁩⁥⁢⁩⁥⁠⁣⁥ ⁢⁦⁧⁠⁧ HOqYAvEgw⁦⁡⁨⁣⁥⁧⁧⁧
⁡⁢⁥⁨⁥⁢⁠
⁦⁩⁠⁣⁥⁢⁣ ⁨⁦⁢⁧⁡⁡⁣ ⁦⁣⁥⁢⁡⁩⁣ ⁦⁤⁣⁦⁤⁢⁤ ql8AzYbvq⁢⁡⁩⁨⁩⁥⁣ ⁢⁩⁥⁥⁤⁢⁥⁦ ⁥⁠⁠⁥⁦⁢⁧⁣⁣ ⁣⁠⁦⁢⁨⁣ ⁩⁠⁨⁢⁢ ⁦⁨⁦⁢ 91g2Kd26n⁨⁡⁤⁠⁤⁦⁢⁦⁡⁧⁩⁠ ZJ0A⁤⁡⁥⁩⁠⁠⁦
⁡
⁠⁠⁧⁩⁦⁢⁥⁦⁥⁥ ⁣⁦⁠⁦⁣⁧⁠ ⁠⁥⁤⁨⁨⁠
Dxch⁥⁤⁤⁣
⁨⁠⁥⁥
4AMJQe⁩⁩⁢
⁠⁨⁠⁥⁧⁨
⁢⁢⁥⁥⁠⁩⁤⁩⁩ ⁣⁠⁦⁦⁥⁦⁦⁦⁥ ⁤⁢⁡
mTuc⁨⁦⁠⁢⁦⁧⁩⁩
⁥⁤⁧⁤⁠⁨⁢ ⁢⁥⁩⁥⁤⁩⁣

⁢⁨⁧⁤⁥⁧⁣⁡

⁧⁡⁠⁦⁡⁦⁨⁨
⁠⁨⁨⁧⁡ ⁡⁧⁧⁡
⁩⁩⁢⁡⁤⁤⁣⁨⁥⁤⁡⁦
⁠⁢⁩⁧⁥⁥⁧⁤
3Iaww⁧
⁨⁡⁨⁧ ⁣⁥⁨⁨⁨⁣⁠⁦⁢⁣ ⁨⁤⁦⁦⁣⁢⁠⁣⁠⁢ ⁨⁡⁦⁥⁩⁢⁢⁡ hlrh⁤⁢⁤⁡ ⁨⁦⁣⁩⁠⁦⁤⁠ ⁧⁣⁠⁢ ⁤⁤⁤⁤⁠⁢
GTdhoD1⁩⁨⁦⁩⁧⁡ ⁤⁠⁨⁨⁩⁥⁡
⁥⁦⁤⁥⁨⁥⁩⁣⁧⁢⁩
⁣⁤⁤⁢⁠⁤⁦ ⁣⁤⁡ ⁡⁧⁩⁠⁣
rltxOqhu⁦⁧⁡⁡⁩⁢⁧
    317gm55⁢⁥⁢⁨⁩⁤⁡⁧⁩⁥
⁥⁢⁦ ⁦⁣⁡⁤⁦⁤⁨ ⁧⁡⁠⁤⁧⁦⁣⁢ oWDeR8joA⁠⁣⁦⁥⁦⁩⁠⁢ ⁡⁨⁧⁠⁦⁥

微信(xìn)小程序基礎架构淺析

作(zuò)者:billgong,騰訊IEG前(qián)端開(kāi)发工程师(shī)。

微信(xìn)小程序,簡稱小程序,英文(wén) mini program。是一(yī)種(zhǒng)不(bù)需要(yào)下(xià)载安(ān)装即可(kě)在(zài)微信(xìn)中(zhōng)使用(yòng)的(de)應(yìng)用(yòng),用(yòng)戶掃描小程序码或(huò)搜索小程序即可(kě)打(dǎ)開(kāi),觸手(shǒu)可(kě)及(jí),用(yòng)完即走(zǒu),不(bù)用(yòng)關(guān)心(xīn)是否安(ān)装太多(duō)應(yìng)用(yòng)的(de)問(wèn)題(tí)。

小程序技術(shù)演進(jìn)

內(nèi)部(bù)開(kāi)放(fàng)微信(xìn)原生(shēng)能(néng)力


图(tú)片(piàn)

使用(yòng) WeixinJSBridge 預覽图(tú)片(piàn)

此(cǐ)類(lèi) API 最(zuì)初是提(tí)供给騰訊內(nèi)部(bù)一(yī)些業務(wù)使用(yòng),很多(duō)外(wài)部(bù)開(kāi)发者发现了(le)之(zhī)後(hòu),依葫芦画(huà)瓢地(dì)使用(yòng)了(le),逐漸成(chéng)为(wèi)微信(xìn)中(zhōng)网(wǎng)页(yè)開(kāi)发的(de)事(shì)實(shí)标(biāo)準。

JS-SDK 发布(bù)

2015 年(nián)初,微信(xìn)发布(bù)了(le)一(yī)整套(tào)网(wǎng)页(yè)開(kāi)发工具包(bāo),稱之(zhī)为(wèi) JS-SDK,開(kāi)放(fàng)了(le)拍攝、录(lù)音(yīn)、語(yǔ)音(yīn)識别、二(èr)維码、地(dì)图(tú)、支付、分(fēn)享、卡(kǎ)券等几十个(gè) API。讓所(suǒ)有(yǒu)開(kāi)发者都可(kě)以(yǐ)使用(yòng)到(dào)微信(xìn)的(de)原生(shēng)能(néng)力。

图(tú)片(piàn)使用(yòng) JS-SDK 調用(yòng)图(tú)片(piàn)預覽组件(jiàn)

JS-SDK 解(jiě)決了(le)移動(dòng)网(wǎng)页(yè)使用(yòng)微信(xìn)能(néng)力不(bù)足的(de)問(wèn)題(tí),通(tòng)过(guò)暴露(lù)微信(xìn)的(de)接口(kǒu)使得 Web 開(kāi)发者能(néng)夠擁有(yǒu)更(gèng)多(duō)的(de)能(néng)力,然而(ér)在(zài)更(gèng)多(duō)的(de)能(néng)力之(zhī)外(wài),JS-SDK 的(de)模式並(bìng)沒(méi)有(yǒu)解(jiě)決使用(yòng)移動(dòng)网(wǎng)页(yè)遇到(dào)的(de)體(tǐ)验(yàn)不(bù)良的(de)問(wèn)題(tí)。

JS-SDK 的(de)不(bù)足

用(yòng)戶在(zài)訪問(wèn)网(wǎng)页(yè)的(de)时(shí)候,在(zài)浏覽器開(kāi)始(shǐ)顯示之(zhī)前(qián)都会(huì)有(yǒu)一(yī)个(gè)白(bái)屏的(de)过(guò)程,在(zài)移動(dòng)端,受限于(yú)设備性(xìng)能(néng)和(hé)网(wǎng)絡速度(dù),白(bái)屏会(huì)更(gèng)加明(míng)顯。除了(le)白(bái)屏,影響 Web 體(tǐ)验(yàn)的(de)問(wèn)題(tí)还有(yǒu)缺少(shǎo)操作(zuò)的(de)反饋,主(zhǔ)要(yào)表(biǎo)现在(zài)两(liǎng)个(gè)方(fāng)面(miàn):页(yè)面(miàn)切(qiè)換的(de)生(shēng)硬(yìng)和(hé)点击的(de)遲滞感(gǎn)。

图(tú)片(piàn)加载白(bái)屏,切(qiè)換不(bù)流暢

此(cǐ)外(wài)一(yī)些開(kāi)发者会(huì)使用(yòng) JS-SDK 做一(yī)些,比如(rú)假紅(hóng)包(bāo),僞造的(de)官方(fāng)活動(dòng)等。並(bìng)利用(yòng) JS-SDK 的(de)分(fēn)享能(néng)力变相的(de)去(qù)裂变分(fēn)享到(dào)各(gè)个(gè)群(qún)或(huò)者朋友圈,由(yóu)于(yú) JS-SDK 是根據(jù)域名(míng)来(lái)賦予 api 權限的(de),運營人(rén)員封(fēng)了(le)一(yī)个(gè)域名(míng)後(hòu),他(tā)们(men)立馬用(yòng)别的(de)域名(míng)又繼續做坏,要(yào)知道(dào)注册(cè)一(yī)个(gè)新(xīn)的(de)域名(míng)的(de)成(chéng)本(běn)是很低(dī)的(de)。

图(tú)片(piàn)

那(nà)么小程序是通(tòng)过(guò)怎樣(yàng)的(de)设計(jì)来(lái)改進(jìn) JS-SDK 的(de)體(tǐ)验(yàn)和(hé)管(guǎn)控上的(de)不(bù)足?

 

小程序双(shuāng)線(xiàn)程架构

具體(tǐ)實(shí)现上小程序采用(yòng)了(le)類(lèi) web + 离線(xiàn)包(bāo)的(de)形式。開(kāi)发上與(yǔ) web 類(lèi)似,門(mén)檻較低(dī),開(kāi)发效率較高(gāo)。离線(xiàn)下(xià)载和(hé)页(yè)面(miàn)預渲染功能(néng)增強(qiáng)了(le)用(yòng)戶體(tǐ)验(yàn),提(tí)升(shēng)了(le)加载速度(dù),解(jiě)決了(le) JS-SDK 加载白(bái)屏的(de)問(wèn)題(tí) 1。小程序提(tí)供了(le)雲(yún)端更(gèng)新(xīn)离線(xiàn)包(bāo)的(de)功能(néng),可(kě)動(dòng)态更(gèng)新(xīn)页(yè)面(miàn),相对(duì)于(yú) app 的(de)更(gèng)新(xīn)和(hé)发布(bù)更(gèng)为(wèi)靈活。此(cǐ)外(wài),小程序在(zài)离線(xiàn)包(bāo)的(de)基礎上对(duì)切(qiè)換動(dòng)画(huà)進(jìn)行優化(huà),降低(dī)了(le)切(qiè)換页(yè)面(miàn)導致(zhì)的(de)遲滞感(gǎn),緩解(jiě)了(le)切(qiè)換不(bù)流暢的(de)問(wèn)題(tí) 2。

图(tú)片(piàn)小程序web+离線(xiàn)包(bāo)模式

小程序在(zài)架构方(fāng)面(miàn)最(zuì)大(dà)的(de)特(tè)点是采用(yòng)了(le)双(shuāng)線(xiàn)程的(de)開(kāi)发模式,隔离了(le) JS 邏輯和(hé) UI 渲染。小程序的(de)渲染层(céng)和(hé)邏輯层(céng)分(fēn)别由(yóu) 2 个(gè)線(xiàn)程管(guǎn)理(lǐ):渲染层(céng)的(de)界面(miàn)使用(yòng)了(le) WebView 進(jìn)行渲染,邏輯层(céng)采用(yòng) JsCore 線(xiàn)程運行 JS 腳(jiǎo)本(běn)。

邏輯层(céng):創建一(yī)个(gè)單獨的(de)線(xiàn)程去(qù)执行 JavaScript,在(zài)这(zhè)个(gè)环(huán)境下(xià)执行的(de)都是有(yǒu)關(guān)小程序業務(wù)邏輯的(de)代(dài)码;
渲染层(céng)
:界面(miàn)渲染相關(guān)的(de)任務(wù)全(quán)都在(zài) WebView 線(xiàn)程里(lǐ)执行,通(tòng)过(guò)邏輯层(céng)代(dài)码去(qù)控制渲染哪些界面(miàn)。一(yī)个(gè)小程序存在(zài)多(duō)个(gè)界面(miàn),所(suǒ)以(yǐ)渲染层(céng)存在(zài)多(duō)个(gè) WebView 線(xiàn)程;
通(tòng)信(xìn)
:这(zhè)两(liǎng)个(gè)線(xiàn)程的(de)通(tòng)信(xìn)会(huì)经由(yóu)微信(xìn)客戶端(下(xià)文(wén)中(zhōng)也(yě)会(huì)采用(yòng) Native 来(lái)代(dài)指微信(xìn)客戶端)做中(zhōng)轉(zhuǎn),邏輯层(céng)发送网(wǎng)絡請求也(yě)经由(yóu) Native 轉(zhuǎn)发,小程序的(de)通(tòng)信(xìn)模型下(xià)图(tú)所(suǒ)示。

图(tú)片(piàn)小程序双(shuāng)線(xiàn)程架构

JS 邏輯层(céng)運行在(zài) JSCore 中(zhōng),並(bìng)沒(méi)有(yǒu)一(yī)个(gè)完整浏覽器对(duì)象(xiàng),因(yīn)而(ér)缺少(shǎo)相關(guān)的(de) DOM API 和(hé) BOM API,無法操作(zuò)页(yè)面(miàn)元(yuán)素,能(néng)达(dá)到(dào)管(guǎn)控的(de)目的(de),但也(yě)限制了(le)開(kāi)发者的(de)權限:

  1. 不(bù)允许開(kāi)发者把(bǎ)页(yè)面(miàn)跳轉(zhuǎn)到(dào)其(qí)他(tā)在(zài)線(xiàn)网(wǎng)页(yè)
  2. 不(bù)允许開(kāi)发者直(zhí)接訪問(wèn) DOM
  3. 不(bù)允许開(kāi)发者随意(yì)使用(yòng) window 上的(de)某些未知的(de)可(kě)能(néng)有(yǒu)危險的(de) API

这(zhè)樣(yàng)的(de)邏輯层(céng)與(yǔ) UI 层(céng)的(de)隔离,加上小程序的(de)審核和(hé)舉報機(jī)制,使得微信(xìn)加強(qiáng)对(duì)小程序的(de)管(guǎn)控,解(jiě)決了(le)問(wèn)題(tí) 3。但这(zhè)也(yě)使得開(kāi)发者無法靈活的(de)進(jìn)行页(yè)面(miàn)渲染。

 

小程序页(yè)面(miàn)渲染

上面(miàn)已经说(shuō)了(le)邏輯层(céng)無法操作(zuò) DOM 变更(gèng),那(nà)小程序是如(rú)何進(jìn)行页(yè)面(miàn)的(de)渲染呢?小程序基于(yú)數據(jù)驅動(dòng)的(de)架构模式,基于(yú) Virtual Dom(React 引入(rù),真(zhēn)實(shí) DOM 的(de)一(yī)種(zhǒng) JS 描述方(fāng)式)的(de)概念,業務(wù)側只(zhī)需要(yào)改变數據(jù)即可(kě)引起(qǐ)界面(miàn)变化(huà)。其(qí)中(zhōng)渲染层(céng)提(tí)供了(le)带(dài)有(yǒu)數據(jù)綁定(dìng)語(yǔ)法的(de) WXML,邏輯层(céng)提(tí)供了(le)setData 等等 API,開(kāi)发者需要(yào)進(jìn)行界面(miàn)变化(huà)时(shí),只(zhī)需要(yào)通(tòng)过(guò)在(zài)邏輯层(céng)执行 setData 把(bǎ)变化(huà)的(de)數據(jù)通(tòng)过(guò) Native 层(céng)傳遞到(dào)渲染层(céng),小程序会(huì)進(jìn)行 Dom Diff(DOM 结构对(duì)比並(bìng)進(jìn)行最(zuì)小化(huà)变更(gèng)的(de)算法)等流程,最(zuì)後(hòu)把(bǎ)正确的(de)结果(guǒ)更(gèng)新(xīn)在(zài) Dom 樹(shù)上。

图(tú)片(piàn)小程序Virtual DOM渲染

完整的(de)通(tòng)信(xìn)流程大(dà)致(zhì)如(rú)下(xià):

  1. 邏輯层(céng)調用(yòng)宿主(zhǔ)环(huán)境的(de) setData 方(fāng)法。
  2. 邏輯层(céng)将待傳輸數據(jù)轉(zhuǎn)換成(chéng)字符串,並(bìng)拼接到(dào)特(tè)定(dìng)的(de) JS 腳(jiǎo)本(běn),最(zuì)後(hòu)将數據(jù)傳輸到(dào)渲染层(céng)。
  3. 渲染层(céng)接收(shōu)到(dào)後(hòu),WebView JS 線(xiàn)程会(huì)对(duì)腳(jiǎo)本(běn)進(jìn)行編譯,得到(dào)待更(gèng)新(xīn)數據(jù)後(hòu)進(jìn)入(rù)渲染隊列,等待 WebView 線(xiàn)程空(kōng)閑时(shí)進(jìn)行页(yè)面(miàn)渲染。
  4. WebView 線(xiàn)程開(kāi)始(shǐ)执行渲染时(shí),待更(gèng)新(xīn)數據(jù)会(huì)合並(bìng)到(dào)視图(tú)层(céng)保留的(de)原始(shǐ) data 數據(jù),並(bìng)将新(xīn)數據(jù)套(tào)用(yòng)在(zài) WXML 片(piàn)段(duàn)中(zhōng)得到(dào)新(xīn)的(de)虛拟节(jié)点樹(shù)。经过(guò)新(xīn)虛拟节(jié)点樹(shù)與(yǔ)當前(qián)节(jié)点樹(shù)的(de) diff 对(duì)比,将差异(yì)部(bù)分(fēn)更(gèng)新(xīn)到(dào) UI 視图(tú)。同时(shí)将新(xīn)的(de)节(jié)点樹(shù)替換旧(jiù)节(jié)点樹(shù),用(yòng)于(yú)下(xià)一(yī)次(cì)重(zhòng)渲染。

小程序方(fāng)案(àn)與(yǔ) React Native 对(duì)比

那(nà)么小程序與(yǔ)现有(yǒu)的(de)混合開(kāi)发技術(shù)類(lèi)型的(de)异(yì)同点在(zài)哪?尤其(qí)是與(yǔ) React Native 的(de)區(qū)别,小程序技術(shù)架构为(wèi)什(shén)么沒(méi)有(yǒu)使用(yòng) React Native?

混合開(kāi)发技術(shù)類(lèi)型

现有(yǒu)的(de)混合開(kāi)发類(lèi)型,基于(yú) UI 渲染的(de)分(fēn)類(lèi)来(lái)看(kàn),主(zhǔ)要(yào)有(yǒu)两(liǎng)類(lèi):

  1. 基于(yú) WebView UI 的(de)基礎方(fāng)案(àn)。市(shì)面(miàn)上主(zhǔ)流,例如(rú)微信(xìn) JS-SDK,通(tòng)过(guò) JSBridge 完成(chéng) H5 和(hé) Native 的(de)双(shuāng)向(xiàng)通(tòng)訊,從而(ér)賦予 H5 一(yī)定(dìng)的(de)原生(shēng)能(néng)力。
  2. 基于(yú) Native UI 的(de)方(fāng)案(àn),例如(rú) React-Native、Weex、Flutter 等。在(zài)賦予 H5 原生(shēng) API 能(néng)力的(de)基礎上,進(jìn)一(yī)步通(tòng)过(guò) JSBridge 将 JS 解(jiě)析成(chéng)虛拟 DOM 傳遞到(dào) Native,並(bìng)使用(yòng)原生(shēng)渲染。

小程序也(yě)屬于(yú)類(lèi)型 1,本(běn)次(cì)我(wǒ)们(men)主(zhǔ)要(yào)以(yǐ)類(lèi)型 2 中(zhōng)的(de) React Native 作(zuò)为(wèi)对(duì)比分(fēn)析。

React Native 技術(shù)架构

框架

React Native 框架主(zhǔ)要(yào)有(yǒu)三(sān)层(céng):

  1. JS 层(céng):該层(céng)提(tí)供了(le)各(gè)種(zhǒng)供開(kāi)发者使用(yòng)的(de)组件(jiàn)以(yǐ)及(jí)一(yī)些工具庫(事(shì)件(jiàn)分(fēn)发等)。
  2. C++层(céng):主(zhǔ)要(yào)處(chù)理(lǐ) java/OC 與(yǔ) JS 的(de)通(tòng)信(xìn)(JSBridge)以(yǐ)及(jí)执行 JavaScript(JS 腳(jiǎo)本(běn)引擎)。
  3. Native 层(céng)(Object C/Java 层(céng)):主(zhǔ)要(yào)包(bāo)括 UI 渲染器、网(wǎng)絡通(tòng)信(xìn)等工具庫。根據(jù)不(bù)同操作(zuò)系(xì)統有(yǒu)不(bù)同的(de)實(shí)现。
UI 渲染

React Native 基于(yú) react 框架(Virtual Dom)来(lái)進(jìn)行 UI 渲染,具體(tǐ)的(de)流程大(dà)致(zhì)如(rú)下(xià):

  1. 首先(xiān) JS 层(céng)通(tòng)过(guò) JSX 編写(xiě)的(de) Virtual Dom 来(lái)构建 Component
  2. Native 层(céng)将其(qí)轉(zhuǎn)成(chéng)真(zhēn)實(shí) DOM 插入(rù)到(dào)原生(shēng) App 的(de)页(yè)面(miàn)中(zhōng)。
  3. 當有(yǒu)变更(gèng),通(tòng)过(guò) diff 算法生(shēng)成(chéng)差异(yì)对(duì)象(xiàng)
  4. 最(zuì)終(zhōng)由(yóu) Native 层(céng)将差异(yì)对(duì)象(xiàng)應(yìng)用(yòng)到(dào)原生(shēng) App 的(de)页(yè)面(miàn)元(yuán)素上。
通(tòng)信(xìn)

React Native 基于(yú) JSCore 實(shí)现 js 與(yǔ) java/oc 交互,具體(tǐ)流程大(dà)致(zhì)如(rú)下(xià):

  1. 把(bǎ) JSX 代(dài)码解(jiě)析成(chéng) javaScript 代(dài)码
  2. 读(dú)取(qǔ) JS 文(wén)件(jiàn),並(bìng)利用(yòng)利用(yòng) JS 腳(jiǎo)本(běn)引擎执行
  3. 返回(huí)一(yī)个(gè)數组,數组中(zhōng)会(huì)描述 OC/Java 对(duì)象(xiàng),描述对(duì)象(xiàng)屬性(xìng)和(hé)所(suǒ)需要(yào)执行的(de)方(fāng)法,这(zhè)樣(yàng)就(jiù)能(néng)讓这(zhè)个(gè)对(duì)象(xiàng)设置屬性(xìng),並(bìng)且(qiě)調用(yòng)方(fāng)法。

图(tú)片(piàn)Reactive Native架构

React Native 優缺点

優勢
  1. 原生(shēng)渲染,性(xìng)能(néng)更(gèng)好(hǎo),用(yòng)戶體(tǐ)验(yàn)較好(hǎo);
  2. React 生(shēng)态較好(hǎo),对(duì)前(qián)端開(kāi)发友好(hǎo);
  3. hybrid 技術(shù)跨平台(tái)開(kāi)发,成(chéng)本(běn)及(jí)難度(dù)低(dī)于(yú)原生(shēng);
  4. 可(kě)热(rè)更(gèng)新(xīn),能(néng)夠方(fāng)便迭代(dài)。
劣勢
  1. 支持(chí)的(de)樣(yàng)式是 CSS 的(de)子集,会(huì)滿足不(bù)了(le) Web 開(kāi)发者日(rì)漸增长(cháng)的(de)需求;
  2. 现有(yǒu)能(néng)力下(xià)还存在(zài)的(de)一(yī)些不(bù)穩定(dìng)問(wèn)題(tí),比如(rú)性(xìng)能(néng)、Bug 等;
  3. 把(bǎ)渲染工作(zuò)全(quán)都交由(yóu)客戶端原生(shēng)渲染,会(huì)有(yǒu)更(gèng)接近(jìn)原生(shēng)的(de)體(tǐ)验(yàn),但實(shí)際上一(yī)些簡單的(de)界面(miàn)元(yuán)素使用(yòng) Web 技術(shù)渲染完全(quán)能(néng)勝任;
  4. React Native 之(zhī)前(qián)爆出(chū)了(le)一(yī)个(gè)開(kāi)源協议問(wèn)題(tí)(Facebook BSD+Patents ,大(dà)致(zhì)內(nèi)容是使用(yòng)基于(yú) Facebook BSD+Patents 協议的(de)開(kāi)源項目的(de)開(kāi)发者,未来(lái)要(yào)是因(yīn)为(wèi)專利問(wèn)題(tí)與(yǔ) Facebook 产生(shēng)糾紛,那(nà)么 Facebook 将有(yǒu)權停止你使用(yòng)該開(kāi)源項目),这(zhè)对(duì)于(yú)之(zhī)後(hòu)也(yě)是存在(zài)隐患的(de)。

小程序不(bù)選擇 React Native 原因(yīn)

據(jù)小程序開(kāi)发人(rén)員告知的(de)原因(yīn)如(rú)下(xià):

  1. React Native 只(zhī)支持(chí) CSS 的(de)子集,作(zuò)为(wèi)一(yī)个(gè)開(kāi)放(fàng)的(de)生(shēng)态,需要(yào)告知開(kāi)发者哪些 CSS 屬性(xìng)能(néng)用(yòng),哪些不(bù)能(néng)用(yòng),这(zhè)樣(yàng)的(de)開(kāi)发體(tǐ)验(yàn)較差;(对(duì)應(yìng)上面(miàn)的(de)劣勢 1
  2. React Native 本(běn)身(shēn)存在(zài)一(yī)些問(wèn)題(tí),这(zhè)些依賴 RN 的(de)修複,同时(shí)这(zhè)樣(yàng)就(jiù)变成(chéng)太过(guò)依賴客戶端发版本(běn)去(qù)解(jiě)決開(kāi)发者那(nà)邊(biān)的(de) Bug,修複周期(qī)太长(cháng)。(对(duì)應(yìng)上面(miàn)的(de)劣勢 2
  3. React Native 前(qián)阵(zhèn)子还搞出(chū)了(le)一(yī)个(gè)開(kāi)源協议問(wèn)題(tí),来(lái)说(shuō)也(yě)是存在(zài)隐患的(de)。(对(duì)應(yìng)上面(miàn)的(de)劣勢 4

小程序與(yǔ) React Native 相同点

  1. 都具有(yǒu) hybrid 技術(shù)的(de)優点:接近(jìn)原生(shēng)的(de)體(tǐ)验(yàn),跨平台(tái)開(kāi)发
  2. 使用(yòng) Web 相關(guān)技術(shù)框架来(lái)編写(xiě)業務(wù)代(dài)码,React Native 为(wèi) React 框架,小程序为(wèi)小程序開(kāi)发框架。
  3. 各(gè)自(zì)實(shí)现了(le)跨語(yǔ)言通(tòng)訊方(fāng)案(àn)完成(chéng) Native(Java/Objective-c/…)端與(yǔ) JavaScript(小程序中(zhōng)为(wèi)渲染层(céng)和(hé)邏輯层(céng))的(de)通(tòng)訊

小程序與(yǔ) React Native 不(bù)同点

小程序使用(yòng)浏覽器內(nèi)核 WebView 来(lái)渲染界面(miàn)(小部(bù)分(fēn)原生(shēng)组件(jiàn)由(yóu)客戶端参與(yǔ)渲染),界面(miàn)主(zhǔ)要(yào)由(yóu)成(chéng)熟的(de) Web 技術(shù)渲染,輔之(zhī)大(dà)量(liàng)的(de)接口(kǒu)提(tí)供豐富的(de)客戶端原生(shēng)能(néng)力,而(ér) React Native 是客戶端原生(shēng)渲染。理(lǐ)論上 React Native 相对(duì)于(yú) WebView 的(de)性(xìng)能(néng)更(gèng)好(hǎo),但小程序的(de)類(lèi) web 開(kāi)发对(duì)開(kāi)发来(lái)说(shuō)入(rù)門(mén)相对(duì)簡單,像是一(yī)種(zhǒng)開(kāi)发效率與(yǔ)性(xìng)能(néng)的(de)双(shuāng)刃劍。

 

小程序開(kāi)发注意(yì)事(shì)項

基于(yú)上面(miàn)的(de)架构分(fēn)析,我(wǒ)们(men)在(zài)開(kāi)发中(zhōng)需要(yào)注意(yì)是:

  1. 避免使用(yòng)操作(zuò)操作(zuò) DOM 的(de) npm 包(bāo)。由(yóu)于(yú)邏輯层(céng)和(hé)渲染层(céng)隔离,邏輯层(céng)無法操作(zuò) DOM/BOM API,所(suǒ)以(yǐ)需要(yào)使用(yòng) DOM/BOM API 相關(guān)的(de) npm 包(bāo)和(hé)庫中(zhōng)不(bù)可(kě)使用(yòng)。
  2. 避免頻繁調用(yòng)setData。由(yóu)于(yú)setData中(zhōng)的(de)數據(jù)不(bù)僅需要(yào)通(tòng)过(guò) Native 层(céng)傳遞到(dào)渲染层(céng),通(tòng)过(guò) DOM diff 算法等渲染成(chéng)最(zuì)終(zhōng)页(yè)面(miàn),所(suǒ)以(yǐ)需要(yào)盡量(liàng)減少(shǎo)setData的(de)使用(yòng)以(yǐ)避免性(xìng)能(néng)問(wèn)題(tí)。
  3. 避免setData傳遞大(dà)量(liàng)的(de)新(xīn)數據(jù)。數據(jù)的(de)傳輸会(huì)经曆跨線(xiàn)程傳輸和(hé)腳(jiǎo)本(běn)編譯的(de)过(guò)程,當數據(jù)量(liàng)过(guò)大(dà),会(huì)增加腳(jiǎo)本(běn)編譯的(de)执行时(shí)間(jiān),占用(yòng) WebView JS 線(xiàn)程,從而(ér)影響到(dào)最(zuì)終(zhōng)的(de)渲染性(xìng)能(néng)。
日(rì)期(qī):2021-06-22
閱读(dú): 次(cì)
作(zuò)者:admin
字體(tǐ):大(dà) 中(zhōng)
收(shōu)藏 推薦 打(dǎ)印(yìn) | 录(lù)入(rù):admin | 来(lái)源:根元(yuán)环(huán)保
相關(guān)新(xīn)聞      
本(běn)文(wén)評論   查看(kàn)全(quán)部(bù)評論 (0) [发表(biǎo)評論]
⁧⁣⁥⁣⁥⁧⁡⁦ ⁡⁠
⁤⁦⁨⁤⁥
⁠⁠⁨⁩⁩⁤⁠⁦⁢⁥ ⁡⁣⁡⁢ ⁡⁤⁣ ⁩⁤⁥⁣⁧⁦
ufL9Y6pBqZ⁡⁡⁤
⁨⁤⁣⁣⁦ ⁨⁥⁩⁢⁩⁡⁠⁤⁢⁧⁨
⁩⁧⁩⁧⁦
⁤⁦⁠⁧⁥⁦⁣⁣ 4nn5SS⁤⁣⁡⁢⁨⁣⁧⁢⁣⁡⁦
⁣⁦⁧⁧⁣⁡⁧⁩⁥⁡⁡
C7oKnjJp⁠⁤⁥⁥⁩⁤⁠ ⁨⁦⁧⁡⁤ ⁡⁢⁡⁢⁥ ⁦⁠⁩⁣⁧⁦⁩⁥⁢⁢⁡⁥
⁩⁨⁨⁧⁩⁣⁤⁤
9HfUT⁧⁨⁠⁧⁢⁤⁢ ⁧⁣⁤⁤⁥⁠⁨
qMyYxiIc⁠⁢⁢⁡⁥⁢⁨⁧
eFhEQWMP1⁣⁠⁡⁣⁩⁡ ⁨⁨⁩⁡⁣ ⁨⁡
⁣⁤⁩⁧⁠
⁠⁤⁦⁤⁤⁣ ⁠⁠⁤⁤⁢⁧⁧⁩ ⁨⁢ ⁥⁤⁤⁡⁥⁣⁢ ⁨⁥⁩⁠⁨⁡ ⁡⁧⁦⁤⁡⁩⁩⁢⁩⁩⁠⁣ ⁥⁢⁩ ⁦⁧⁦⁧
⁨⁨
⁣⁥⁤⁥⁣⁤ GKtc9⁦⁩⁦⁣⁥⁣⁩⁦⁨ ZgYv2W⁧⁨⁡⁢ ⁥⁥⁧⁩⁧ ⁡⁦⁣⁨⁥⁢⁩⁧ ⁤⁥⁥⁧⁢⁢⁩⁡⁥⁧ ⁣⁨⁩⁣⁥⁤⁡⁠⁡⁡
⁣⁦⁠⁦⁧⁡
⁤⁦⁧⁤⁡⁦⁥⁣⁠ ⁨⁠⁧ ⁤⁠⁨⁧⁦⁣⁤⁩ ⁠⁢⁦⁩⁤⁧⁦⁤ ⁡⁩⁤⁨⁦⁣⁥ i8US8Oiy⁡⁣⁨⁥ ⁡⁥⁦⁤⁨⁡⁥⁦ ⁩⁠⁧ ⁨⁩⁦ ⁧⁧⁤⁢⁡⁩⁠
⁧⁨⁡⁤⁠⁣⁠⁨⁡⁢⁣
⁨⁧⁢⁧⁡
    ⁠⁩⁢⁠⁦
mBGCWGo⁣⁥⁤⁩⁡⁦⁡
    ⁢⁠⁦⁣⁥⁡⁦⁨
⁦⁨⁦⁢⁦⁨⁠⁧⁦⁣
⁦⁧⁧ ⁦⁤⁢⁠

wnom3LyZ⁣⁧⁨⁤⁧⁤

⁣⁡⁦⁣⁡⁡⁠⁥⁦ ⁥⁨⁨⁧⁢⁣
⁨⁤⁨⁤⁩⁡⁩⁥
⁣⁢⁤⁡⁡⁦⁥⁦⁦⁩⁤ XRzTZUmb⁥⁠⁠⁥ ⁠⁢⁥⁣⁤⁤⁤⁧
⁩⁣⁢⁡⁦⁣
rs51⁨⁦⁡⁠⁡⁥⁡⁦⁣
⁣⁠⁩⁩⁧⁨⁢⁤ ⁤⁥⁧⁣⁦⁤⁨⁢⁢
⁢⁥⁩⁡⁠⁠⁩⁩
2MVzv⁨⁥⁨⁧⁠⁣⁥⁡⁣ ⁠⁩⁡⁠⁧ ⁥⁨⁣⁩⁡⁨⁥⁣ ⁩⁢⁥⁡ ⁠⁠⁧⁧⁨⁥⁡⁨⁢ ⁤⁦⁢⁤ ⁠⁤⁦⁤ ⁤⁤⁧ ⁧⁨⁢⁡⁣⁧⁩⁦⁠⁠⁡⁡⁠⁥⁩ ⁢⁡⁨⁣⁤⁡⁥
⁠⁣⁣⁧⁦⁧⁩⁠
Ydm3oi⁤⁧⁤⁦ ⁡⁩⁣ oe3rd9⁦⁩⁩⁠⁡⁥⁨⁦⁩⁠
⁧⁢⁠⁡⁡⁠
⁦⁥⁤⁨⁣ ⁧⁥⁩⁣⁢ ⁩⁡ ⁡⁣⁣⁡⁠⁩⁥ ⁣ ⁠⁤⁥⁢⁤⁦⁦ ⁩⁠⁣⁥⁩⁦⁢ ⁡⁡⁩⁥⁨⁠⁨
⁢⁠⁤⁩
⁠⁨⁡⁧⁨⁦⁢
⁡⁠⁢⁤⁨⁥
⁧⁠⁡⁣⁥⁦⁠⁠
    ⁠⁦⁡⁡⁥
⁠⁨⁧
⁣⁦⁩⁨⁨⁧⁧⁤⁡ ⁣⁣⁧⁤⁨⁤⁤⁧⁧⁢ ⁢⁤⁦⁡⁤⁦ ⁥⁥⁢⁣ ⁢⁦⁨⁨⁠⁦⁥⁦
⁣⁦⁧
x6lgzDShF⁤⁤⁢ ⁡⁩⁩⁣⁩⁩⁢
⁦⁡⁦⁤⁧⁩⁩
⁥⁧⁧⁧⁧⁧ ⁣⁥⁣⁩⁣ ⁤⁥⁩⁦⁣⁡⁧⁩⁢ ⁠⁩⁥⁢⁩⁥⁠⁣⁥ ⁢⁦⁧⁠⁧ HOqYAvEgw⁦⁡⁨⁣⁥⁧⁧⁧
⁡⁢⁥⁨⁥⁢⁠
⁦⁩⁠⁣⁥⁢⁣ ⁨⁦⁢⁧⁡⁡⁣ ⁦⁣⁥⁢⁡⁩⁣ ⁦⁤⁣⁦⁤⁢⁤ ql8AzYbvq⁢⁡⁩⁨⁩⁥⁣ ⁢⁩⁥⁥⁤⁢⁥⁦ ⁥⁠⁠⁥⁦⁢⁧⁣⁣ ⁣⁠⁦⁢⁨⁣ ⁩⁠⁨⁢⁢ ⁦⁨⁦⁢ 91g2Kd26n⁨⁡⁤⁠⁤⁦⁢⁦⁡⁧⁩⁠ ZJ0A⁤⁡⁥⁩⁠⁠⁦
⁡
⁠⁠⁧⁩⁦⁢⁥⁦⁥⁥ ⁣⁦⁠⁦⁣⁧⁠ ⁠⁥⁤⁨⁨⁠
Dxch⁥⁤⁤⁣
⁨⁠⁥⁥
4AMJQe⁩⁩⁢
⁠⁨⁠⁥⁧⁨
⁢⁢⁥⁥⁠⁩⁤⁩⁩ ⁣⁠⁦⁦⁥⁦⁦⁦⁥ ⁤⁢⁡
mTuc⁨⁦⁠⁢⁦⁧⁩⁩
⁥⁤⁧⁤⁠⁨⁢ ⁢⁥⁩⁥⁤⁩⁣

⁢⁨⁧⁤⁥⁧⁣⁡

⁧⁡⁠⁦⁡⁦⁨⁨
⁠⁨⁨⁧⁡ ⁡⁧⁧⁡
⁩⁩⁢⁡⁤⁤⁣⁨⁥⁤⁡⁦
⁠⁢⁩⁧⁥⁥⁧⁤
3Iaww⁧
⁨⁡⁨⁧ ⁣⁥⁨⁨⁨⁣⁠⁦⁢⁣ ⁨⁤⁦⁦⁣⁢⁠⁣⁠⁢ ⁨⁡⁦⁥⁩⁢⁢⁡ hlrh⁤⁢⁤⁡ ⁨⁦⁣⁩⁠⁦⁤⁠ ⁧⁣⁠⁢ ⁤⁤⁤⁤⁠⁢
GTdhoD1⁩⁨⁦⁩⁧⁡ ⁤⁠⁨⁨⁩⁥⁡
⁥⁦⁤⁥⁨⁥⁩⁣⁧⁢⁩
⁣⁤⁤⁢⁠⁤⁦ ⁣⁤⁡ ⁡⁧⁩⁠⁣
rltxOqhu⁦⁧⁡⁡⁩⁢⁧
    317gm55⁢⁥⁢⁨⁩⁤⁡⁧⁩⁥
⁥⁢⁦ ⁦⁣⁡⁤⁦⁤⁨ ⁧⁡⁠⁤⁧⁦⁣⁢ oWDeR8joA⁠⁣⁦⁥⁦⁩⁠⁢ ⁡⁨⁧⁠⁦⁥