微信小程序底層原理剖析

微信小程序底層原理剖析


隨著前端技術(shù)的不斷演進(jìn)冕茅,目前市面上的移動(dòng)端產(chǎn)品有像大前端轉(zhuǎn)換的趨勢(shì)御铃。開(kāi)發(fā)一個(gè)產(chǎn)品主流上大致有5種開(kāi)發(fā)模式官辽,包括 Native APP 原生應(yīng)用、WebAPP 網(wǎng)頁(yè)應(yīng)用搓劫、Hybrid App 混合式開(kāi)發(fā)瞧哟、ReactNative、輕應(yīng)用小程序枪向。開(kāi)發(fā)一款 APP勤揩,如果注重性能,不需要過(guò)多的動(dòng)態(tài)內(nèi)容秘蛔,可以選擇原生應(yīng)用來(lái)開(kāi)發(fā)陨亡。如果性能要求不高,只是需要點(diǎn)開(kāi)即用深员,那么 WebAPP 即可滿(mǎn)足负蠕。如果這兩種要求都必須滿(mǎn)足,那么 Hybrid App 混合式的開(kāi)發(fā)是一種折中的方法倦畅,將兩者優(yōu)勢(shì)互補(bǔ)遮糖,滿(mǎn)足大部分的需求。近幾年叠赐,出現(xiàn)了類(lèi)似 ReactNative 和小程序這種深度定制的開(kāi)發(fā)模式欲账,開(kāi)發(fā)只需要寫(xiě) Javascript 就可以產(chǎn)出性能可與原生媲美的產(chǎn)品,通過(guò)腳本語(yǔ)言面向開(kāi)發(fā)者芭概,實(shí)際跑的確是的原生組件赛不。小程序也好,其他框架也好罢洲,理解他們的設(shè)計(jì)緣由踢故、實(shí)現(xiàn)原理,還是能學(xué)到很多很多東西的。

從兩大線程說(shuō)開(kāi)

小程序由兩大線程組成:負(fù)責(zé)界面的線程(view thread)和服務(wù)線程(appservice thread)殿较,各司其職由互相配合耸峭。兩個(gè)線程分別用于渲染層和邏輯層,渲染層的界面使用了 WebView 進(jìn)行渲染斜脂,通過(guò)邏輯層代碼去控制渲染哪些界面抓艳,如果一個(gè)小程序存在多個(gè)界面触机,則渲染層存在多個(gè) WebView 線程帚戳;邏輯層采用一個(gè)單獨(dú)的 JsCore 線程運(yùn)行 JS 腳本,在這個(gè)環(huán)境下執(zhí)行的都是有關(guān)小程序業(yè)務(wù)邏輯的代碼儡首。套用一張官方的圖來(lái)解釋片任。

為什么要這么設(shè)計(jì)呢?主要還是處于管控和安全上的考慮蔬胯。我們需要阻止開(kāi)發(fā)者使用一些瀏覽器提供的对供,諸如跳轉(zhuǎn)頁(yè)面、操作 DOM氛濒、動(dòng)態(tài)執(zhí)行腳本的開(kāi)放性接口产场。

小程序的生命周期

小程序的生命周期借鑒了Android的生命周期,如果你了解過(guò)Android的APP開(kāi)發(fā)舞竿,那么理解小程序的就會(huì)很簡(jiǎn)單京景。

界面線程有四大狀態(tài):

  1. 初始化狀態(tài):初始化界面線程所需要的工作,包括工作機(jī)制骗奖,基本和我們開(kāi)發(fā)者沒(méi)有關(guān)系确徙,等初始化完畢就向“服務(wù)線程”發(fā)送初始化完畢信號(hào),然后進(jìn)入等待傳回初始化數(shù)據(jù)狀態(tài)执桌。

  2. 首次渲染狀態(tài):收到“服務(wù)線程”發(fā)來(lái)的初始化數(shù)據(jù)后(就是 json和js中的data數(shù)據(jù))鄙皇,就開(kāi)始渲染小程序界面,渲染完畢后仰挣,發(fā)送“首次渲染完畢信號(hào)”給服務(wù)線程伴逸,并將頁(yè)面展示給用戶(hù)。

  3. 持續(xù)渲染狀態(tài):此時(shí)界面線程繼續(xù)一直等待“服務(wù)線程”通過(guò)this.setdata()函數(shù)發(fā)送來(lái)的界面數(shù)據(jù)膘壶,只要收到就重新局部渲染错蝴,也因此只要更新數(shù)據(jù)并發(fā)送信號(hào),界面就自動(dòng)更新香椎。

  4. 結(jié)束狀態(tài):結(jié)束渲染漱竖。

服務(wù)線程五大狀態(tài):

  1. 初始化狀態(tài):無(wú)需和其他模塊交流,跟小程序開(kāi)發(fā)也沒(méi)多大關(guān)聯(lián)畜伐,此階段就是啟動(dòng)服務(wù)線程所需的基本功能馍惹,比如信號(hào)發(fā)送模塊。系統(tǒng)的初始化工作完畢,就調(diào)用自定義的onload和onshow万矾,

然后等待界面線程的“界面線程初始化完成”信號(hào)悼吱。

onload是只會(huì)首次渲染的時(shí)候執(zhí)行一次,onshow是每次界面切換都會(huì)執(zhí)行良狈,簡(jiǎn)單理解后添,這就是唯一差別。

  1. 等待激活狀態(tài):接收到“界面線程初始化完成”信號(hào)后薪丁,將初始化數(shù)據(jù)發(fā)送給“界面線程”遇西,等待界面線程完成初次渲染。

  2. 激活狀態(tài):收到界面線程發(fā)送來(lái)的“首次渲染完成”信號(hào)后严嗜,就進(jìn)入激活狀態(tài)既程序的正常運(yùn)行狀態(tài)粱檀,并調(diào)用自定義的onReady()函數(shù)。

此狀態(tài)下就可以通過(guò) this.setData 函數(shù)發(fā)送界面數(shù)據(jù)給界面線程進(jìn)行局部渲染漫玄,更新頁(yè)面茄蚯。

  1. 后臺(tái)運(yùn)行狀態(tài):如果界面進(jìn)入后臺(tái),服務(wù)線程就進(jìn)入后臺(tái)運(yùn)行狀態(tài)睦优,從目前的官方解讀來(lái)說(shuō)渗常,這個(gè)狀態(tài)挺奇怪的,和激活狀態(tài)是相同的汗盘,也可以通過(guò)setdata函數(shù)更新界面的皱碘。畢竟小程序的框架剛推出,應(yīng)該后續(xù)會(huì)有很大不同吧衡未。

小程序雙線程間的通信

把開(kāi)發(fā)者的 JS 邏輯代碼放到單獨(dú)的線程去運(yùn)行尸执,但在 Webview 線程里,開(kāi)發(fā)者就沒(méi)法直接操作 DOM缓醋。那要怎么去實(shí)現(xiàn)動(dòng)態(tài)更改界面呢如失?

前面我們知道,邏輯層和渲染層的通信會(huì)由 Native (微信客戶(hù)端)做中轉(zhuǎn)送粱,邏輯層發(fā)送網(wǎng)絡(luò)請(qǐng)求也經(jīng)由 Native 轉(zhuǎn)發(fā)褪贵。這是不是意味著,我們可以把 DOM 的更新通過(guò)簡(jiǎn)單的數(shù)據(jù)通信來(lái)實(shí)現(xiàn)呢抗俄?

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

在這里我們可以用上动雹,如圖:

  1. 在渲染層把 WXML 轉(zhuǎn)化成對(duì)應(yīng)的 JS 對(duì)象槽卫。

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

  3. 經(jīng)過(guò)對(duì)比前后差異震蒋,把差異應(yīng)用在原來(lái)的 DOM 樹(shù)上,更新界面躲庄。

我們通過(guò)把 WXML 轉(zhuǎn)化為數(shù)據(jù)查剖,通過(guò) Native 進(jìn)行轉(zhuǎn)發(fā),來(lái)實(shí)現(xiàn)邏輯層和渲染層的交互和通信噪窘。而這樣完整的一套框架笋庄,基本上都是通過(guò)小程序的基礎(chǔ)庫(kù)來(lái)完成的。

小程序的基礎(chǔ)組件

native層就是小程序的框架倔监,就像常用的react框架一樣直砂,這個(gè)框架里封裝了ui層組件和邏輯層組件,這些組件可以通過(guò)微信app提供的接口調(diào)用手機(jī)硬件信息

這些基礎(chǔ)組件庫(kù)是JavaScript編寫(xiě)的丐枉,它可以被注入到渲染層和邏輯層運(yùn)行哆键。主要用于:

  • 在渲染層掘托,提供各類(lèi)組件來(lái)組件頁(yè)面的元素

  • 在邏輯層瘦锹,提供各種API來(lái)處理各種元素。

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

由于小程序的渲染層和邏輯層是兩個(gè)線程管理泪掀,兩個(gè)線程各自注入了基礎(chǔ)庫(kù)听绳。小程序的基礎(chǔ)庫(kù)不會(huì)被打包在某個(gè)小程序的代碼包里邊,它會(huì)被提前內(nèi)置在微信客戶(hù)端异赫。

總結(jié)

小程序考慮到了原生開(kāi)發(fā)和純web開(kāi)發(fā)的不利之處:用純客戶(hù)端原生技術(shù)來(lái)編寫(xiě)小程序 的話椅挣,小程序代碼需要與微信代碼一起編包,顯然過(guò)于繁重了塔拳;而用純 Web 技術(shù)來(lái)渲染小程序鼠证,在一些有復(fù)雜交互的頁(yè)面上可能會(huì)面臨一些性能問(wèn)題。

因此靠抑,小程序選擇了 Hybrid 的渲染方式量九,將UI渲染跟 JavaScript 的腳本執(zhí)行分在了兩個(gè)線程,巧妙了解決了上述問(wèn)題颂碧,作為一種全新的前端開(kāi)發(fā)框架能夠很快成為許多開(kāi)發(fā)者的最?lèi)?ài)也就不足為奇了荠列。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市载城,隨后出現(xiàn)的幾起案子肌似,更是在濱河造成了極大的恐慌,老刑警劉巖诉瓦,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件川队,死亡現(xiàn)場(chǎng)離奇詭異受楼,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)呼寸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)艳汽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人对雪,你說(shuō)我怎么就攤上這事河狐。” “怎么了瑟捣?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵馋艺,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我迈套,道長(zhǎng)捐祠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任桑李,我火速辦了婚禮踱蛀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贵白。我一直安慰自己率拒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布禁荒。 她就那樣靜靜地躺著猬膨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呛伴。 梳的紋絲不亂的頭發(fā)上勃痴,一...
    開(kāi)封第一講書(shū)人閱讀 51,208評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音热康,去河邊找鬼沛申。 笑死,一個(gè)胖子當(dāng)著我的面吹牛褐隆,可吹牛的內(nèi)容都是我干的污它。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼庶弃,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼衫贬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起歇攻,我...
    開(kāi)封第一講書(shū)人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤固惯,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后缴守,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體葬毫,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡镇辉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贴捡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忽肛。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖烂斋,靈堂內(nèi)的尸體忽然破棺而出屹逛,到底是詐尸還是另有隱情,我是刑警寧澤汛骂,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布罕模,位于F島的核電站,受9級(jí)特大地震影響帘瞭,放射性物質(zhì)發(fā)生泄漏淑掌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一蝶念、第九天 我趴在偏房一處隱蔽的房頂上張望抛腕。 院中可真熱鬧,春花似錦祸轮、人聲如沸兽埃。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至舷夺,卻和暖如春苦酱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背给猾。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工疫萤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敢伸。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓扯饶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親池颈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子尾序,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354