日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

七大热门小程序框架横评,谁是性能之王

發(fā)布時間:2023/12/18 70 豆豆
生活随笔 收集整理的這篇文章主要介紹了 七大热门小程序框架横评,谁是性能之王 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者:董宏平(hiyuki),滴滴出行小程序負責人,mpx框架負責人及核心作者

隨著小程序在商業(yè)上的巨大成功,小程序開發(fā)在國內(nèi)前端領(lǐng)域越來越受到重視,為了方便廣大開發(fā)者更好地進行小程序開發(fā),各類小程序框架也層出不窮,呈現(xiàn)出百花齊放的態(tài)勢。但是到目前為止,業(yè)內(nèi)一直沒有出現(xiàn)一份全面、詳細、客觀、公正的小程序框架測評報告,為小程序開發(fā)者在技術(shù)選型時提供參考。于是我便籌劃推出一系列文章,對業(yè)內(nèi)流行的小程序框架進行一次全方位的、客觀公正的測評,本文是系列文章的第一篇——運行時性能篇。

在本文中,我們會對下列框架進行運行時性能測試(排名不分先后):

  • wepy2(https://github.com/Tencent/wepy) @2.0.0-alpha.20

  • uniapp(https://github.com/dcloudio/u...) @2.0.0-26120200226001

  • mpx(https://github.com/didi/mpx) @2.5.3

  • chameleon(https://github.com/didi/chame...) @1.0.5

  • mpvue(https://github.com/Meituan-Di...) @2.0.6

  • kbone(https://github.com/Tencent/kb...) @0.8.3

  • taro next(https://github.com/NervJS/taro) @3.0.0-alpha.5

其中對于kbone和taro next均以vue作為業(yè)務(wù)框架進行測試。

運行時性能的測試內(nèi)容包括以下幾個維度:

  • 框架運行時體積

  • 頁面渲染耗時

  • 頁面更新耗時

  • 局部更新耗時

  • setData調(diào)用次數(shù)

  • setData發(fā)送數(shù)據(jù)大小

框架性能測試demo全部存放于https://github.com/hiyuki/mp-... 中,歡迎廣大開發(fā)者進行驗證糾錯及補全;

測試方案

為了使測試結(jié)果真實有效,我基于常見的業(yè)務(wù)場景構(gòu)建了兩種測試場景,分別是動態(tài)測試場景和靜態(tài)測試場景。

動態(tài)測試場景

動態(tài)測試中,視圖基于數(shù)據(jù)動態(tài)渲染,靜態(tài)節(jié)點較少,視圖更新耗時和setData調(diào)用情況是該測試場景中的主要測試點。

動態(tài)測試demo模擬了實際業(yè)務(wù)中常見的長列表+多tab場景,該demo中存在兩份優(yōu)惠券列表數(shù)據(jù),一份為可用券數(shù)據(jù),另一份為不可用券數(shù)據(jù),其中同一時刻視圖中只會渲染展示其中一份數(shù)據(jù),可以在上方的操作區(qū)模擬對列表數(shù)據(jù)的各種操作及視圖展示切換(切tab)。

動態(tài)測試demo

動態(tài)測試demo

在動態(tài)測試中,我在外部通過函數(shù)代理的方式在初始化之前將App、Page和Component構(gòu)造器進行代理,通過mixin的方式在Page的onLoad和Component的created鉤子中注入setData攔截邏輯,對所有頁面和組件的setData調(diào)用進行監(jiān)聽,并統(tǒng)計小程序的視圖更新耗時及setData調(diào)用情況。該測試方式能夠做到對框架代碼的零侵入,能夠跟蹤到小程序全量的setData行為并進行獨立的耗時計算,具有很強的普適性,代碼具體實現(xiàn)可以查看https://github.com/hiyuki/mp-...

靜態(tài)測試場景

靜態(tài)測試模擬業(yè)務(wù)中靜態(tài)頁面的場景,如運營活動和文章等頁面,頁面內(nèi)具備大量的靜態(tài)節(jié)點,而沒有數(shù)據(jù)動態(tài)渲染,初始ready耗時是該場景下測試的重心。

靜態(tài)測試demo使用了我去年發(fā)表的一篇技術(shù)文章的html代碼進行小程序適配構(gòu)建,其中包含大量靜態(tài)節(jié)點及文本內(nèi)容。

靜態(tài)測試demo

靜態(tài)測試demo

測試流程及數(shù)據(jù)

以下所有耗時類的測試數(shù)據(jù)均為微信小程序中真機進行5次測試計算平均值得出,單位均為ms。Ios測試環(huán)境為手機型號iPhone 11,系統(tǒng)版本13.3.1,微信版本7.0.12,安卓測試環(huán)境為手機型號小米9,系統(tǒng)版本Android10,微信版本7.0.12。

為了使數(shù)據(jù)展示不過于混亂復(fù)雜,文章中所列的數(shù)據(jù)以Ios的測試結(jié)果為主,安卓測試結(jié)論與Ios相符,整體耗時比Ios高3~4倍左右,所有的原始測試數(shù)據(jù)存放在https://github.com/hiyuki/mp-...

由于transform-runtime引入的core-js會對框架的運行時體積和運行耗時帶來一定影響,且不是所有的框架都會在編譯時開啟transform-runtime,為了對齊測試環(huán)境,下述測試均在transform-runtime關(guān)閉時進行。

框架運行時體積

由于不是所有框架都能夠使用webpack-bundle-analyzer得到精確的包體積占用,這里我通過將各框架生成的demo項目體積減去native編寫的demo項目體積作為框架的運行時體積。


demo總體積(KB)框架運行時體積(KB)
native270
wepy26639
uniapp11487
mpx7851
chameleon136109
mpvue10376
kbone395368
taro next183156

該項測試的結(jié)論為:
native > wepy2 > mpx > mpvue > uniapp > chameleon > taro next > kbone

結(jié)論分析:

  • wepy2和mpx在框架運行時體積上控制得最好;

  • taro next和kbone由于動態(tài)渲染的特性,在dist中會生成遞歸渲染模板/組件,所以占用體積較大。

頁面渲染耗時(動態(tài)測試)

我們使用刷新頁面操作觸發(fā)頁面重新加載,對于大部分框架來說,頁面渲染耗時是從觸發(fā)刷新操作到頁面執(zhí)行onReady的耗時,但是對于像kbone和taro next這樣的動態(tài)渲染框架,頁面執(zhí)行onReady并不代表視圖真正渲染完成,為此,我們設(shè)定了一個特殊規(guī)則,在頁面onReady觸發(fā)的1000ms內(nèi),在沒有任何操作的情況下出現(xiàn)setData回調(diào)時,以最后觸發(fā)的setData回調(diào)作為頁面渲染完成時機來計算真實的頁面渲染耗時,測試結(jié)果如下:


頁面渲染耗時
native60.8
wepy264
uniapp56.4
mpx52.6
chameleon56.4
mpvue117.8
kbone98.6
taro next89.6

該項測試的耗時并不等同于真實的渲染耗時,由于小程序自身沒有提供performance api,真實渲染耗時無法通過js準確測試得出,不過從得出的數(shù)據(jù)來看該項數(shù)據(jù)依然具備一定的參考意義。

該項測試的結(jié)論為:
mpx ≈ chameleon ≈ uniapp ≈ native ≈ wepy2 > taro next ≈ kbone ≈ mpvue

結(jié)論分析:

  • 由于mpvue全量在頁面進行渲染,kbone和taro next采用了動態(tài)渲染技術(shù),頁面渲染耗時較長,其余框架并無太大區(qū)別。

頁面更新耗時(無后臺數(shù)據(jù))

這里后臺數(shù)據(jù)的定義為data中存在但當前頁面渲染中未使用到的數(shù)據(jù),在這個demo場景下即為不可用券的數(shù)據(jù),當前會在不可用券為0的情況下,對可用券列表進行各種操作,并統(tǒng)計更新耗時。

更新耗時的計算方式是從數(shù)據(jù)操作事件觸發(fā)開始到對應(yīng)的setData回調(diào)完成的耗時

mpvue中使用了當前時間戳(new Date)作為超時依據(jù)對setData進行了超時時間為50ms的節(jié)流操作,該方式存在嚴重問題,當vue內(nèi)單次渲染同步流程執(zhí)行耗時超過50ms時,后續(xù)組件patch觸發(fā)的setData會突破這個節(jié)流限制,以50ms每次的頻率對setData進行高頻無效調(diào)用。在該性能測試demo中,當優(yōu)惠券數(shù)量超過500時,界面就會完全卡死。為了順利跑完整個測試流程,我對該問題進行了簡單修復(fù),使用setTimeout重寫了節(jié)流部分,確保在vue單次渲染流程同步執(zhí)行完畢后才會調(diào)用setData發(fā)送合并數(shù)據(jù),之后mpvue的所有性能測試都是基于這個patch版本來進行的,該patch版本存放在https://github.com/hiyuki/mp-...

理論上來講native的性能在進行優(yōu)化的前提下一定是所有框架的天花板,但是在日常業(yè)務(wù)開發(fā)中我們可能無法對每一次setData都進行優(yōu)化,以下性能測試中所有的native數(shù)據(jù)均采用修改數(shù)據(jù)后全量發(fā)送的形式來實現(xiàn)。

第一項測試我們使用新增可用券(100)操作將可用券數(shù)量由0逐級遞增到1000:


1002003004005006007008009001000
native84.669.871.67577.278.882.893.293.4105.4
wepy2118.4168.6204.6246.4288.6347.8389.2434.2496539
uniapp121.21009698.297.899.6104102.4109.4107.6
mpx110.487.282.28380.679.686.690.689.296.4
chameleon116.8115.4117119.6122125.2133.8133.2144.8145.6
mpvue112.8121.2140169198.8234.2278.8318.4361.4408.2
kbone556.4762.4991.61220.61468.81689.61933.22150.423892620.6
taro next470604.6759.6902.41056.212281393.41536.21707.81867.2

然后我們按順序逐項點擊刪除可用券(all) > 新增可用券(1000) > 更新可用券(1) > 更新可用券(all) > 刪除可用券(1):


delete(all)add(1000)update(1)update(all)delete(1)
native32.8295.692.292.283
wepy256.8726.449.2535530.8
uniapp43.6584.454.8144.8131.2
mpx41.8489.652.6169.4165.6
chameleon39765.695.6237.8144.8
mpvue103.6669.4404.4414.8433.6
kbone120.249782356.42419.42357
taro next126.63930.61607.81788.62318.2

該項測試中初期我update(all)的邏輯是循環(huán)對每個列表項進行更新,形如listData.forEach((item)=>{item.count++}),發(fā)現(xiàn)在chameleon框架中執(zhí)行界面會完全卡死,追蹤發(fā)現(xiàn)chameleon框架中沒有對setData進行異步合并處理,而是在數(shù)據(jù)變動時直接同步發(fā)送,這樣在數(shù)據(jù)量為1000的場景下用該方式進行更新會高頻觸發(fā)1000次setData,導(dǎo)致界面卡死;對此,我在chameleon框架的測試demo中,將update(all)的邏輯調(diào)整為深clone產(chǎn)生一份更新后的listData,再將其整體賦值到this.listData當中,以確保該項測試能夠正常進行。

該項測試的結(jié)論為:
native > mpx ≈ uniapp > chameleon > mpvue > wepy2 > taro next > kbone

結(jié)論分析:

  • mpx和uniapp在框架內(nèi)部進行了完善的diff優(yōu)化,隨著數(shù)據(jù)量的增加,兩個框架的新增耗時沒有顯著上升;

  • wepy2會在數(shù)據(jù)變更時對props數(shù)據(jù)也進行setData,在該場景下造成了大量的無效性能損耗,導(dǎo)致性能表現(xiàn)不佳;

  • kbone和taro next采用了動態(tài)渲染方案,每次新增更新時會發(fā)送大量描述dom結(jié)構(gòu)的數(shù)據(jù),與此同時動態(tài)遞歸渲染的耗時也遠大于常規(guī)的靜態(tài)模板渲染,使得這兩個框架在所有的更新場景下耗時都遠大于其他框架。

頁面更新耗時(有后臺數(shù)據(jù))

刷新頁面后我們使用新增不可用券(1000)創(chuàng)建后臺數(shù)據(jù),觀察該操作是否會觸發(fā)setData并統(tǒng)計耗時


back add(1000)
native45.2
wepy2174.6
uniapp89.4
mpx0
chameleon142.6
mpvue134
kbone0
taro next0

mpx進行setData優(yōu)化時inspired by vue,使用了編譯時生成的渲染函數(shù)跟蹤模板數(shù)據(jù)依賴,在后臺數(shù)據(jù)變更時不會進行setData調(diào)用,而kbone和taro next采用了動態(tài)渲染技術(shù)模擬了web底層環(huán)境,在上層完整地運行了vue框架,也達到了同樣的效果。

然后我們執(zhí)行和上面無后臺數(shù)據(jù)時相同的操作進行耗時統(tǒng)計,首先是遞增100:


1002003004005006007008009001000
native8869.871.280.879.484.489.893.299.6108
wepy2121173.4213.6250298345.6383434.8476.8535.6
uniapp135.4112.4110.6106.4109.6107.2114.4116118.8117.4
mpx112.686.284.686.89087.291.288.892.493.4
chameleon178.4178.2186.4184.6192.6203.8210217.6232.6236.8
mpvue139151173.4194231.4258.8303.4340.4384.6429.4
kbone559.8746.6980.61226.81450.61705.41927.22154.82367.82617
taro next482.6626.2755909.610851233.213841568.61740.61883.8

然后按下表操作順序逐項點擊統(tǒng)計


delete(all)add(1000)update(1)update(all)delete(1)
native43.4299.889.28987.2
wepy243.2762.450533522.4
uniapp57.8589.862.6160.6154.4
mpx45.8490.852.8167166
chameleon93.8837184.6318220.8
mpvue124.8696.2423.4419430.6
kbone121.44978.22331.22448.42348
taro next129.83947.21610.41813.82290.2

該項測試的結(jié)論為:
native > mpx > uniapp > chameleon > mpvue > wepy2 > taro next > kbone

結(jié)論分析:

  • 具備模板數(shù)據(jù)跟蹤能力的三個框架mpx,kbone和taro next在有后臺數(shù)據(jù)場景下耗時并沒有顯著增加;

  • wepy2當中的diff精度不足,耗時也沒有產(chǎn)生明顯變化;

  • 其余框架由于每次更新都會對后臺數(shù)據(jù)進行deep diff,耗時都產(chǎn)生了一定提升。

頁面更新耗時(大數(shù)據(jù)量場景)

由于mpvue和taro next的渲染全部在頁面中進行,而kbone的渲染方案會額外新增大量的自定義組件,這三個框架都會在優(yōu)惠券數(shù)量達到2000時崩潰白屏,我們排除了這三個框架對其余框架進行大數(shù)據(jù)量場景下的頁面更新耗時測試

首先還是在無后臺數(shù)據(jù)場景下使用新增可用券(1000)將可用券數(shù)量遞增至5000:


10002000300040005000
native332.6350412.6498.2569.4
wepy2970.21531.42015.22890.63364.2
uniapp655.2593.4655675.6718.8
mpx532.2496548.6564601.8
chameleon805.4839.6952.81086.61291.8

然后點擊新增不可用券(5000)將后臺數(shù)據(jù)量增加至5000,再測試可用券數(shù)量遞增至5000的耗時:


back add(5000)
native117.4
wepy2511.6
uniapp285
mpx0
chameleon824

10002000300040005000
native349.8348.4430.4497594.8
wepy2112818722470.43263.44075.8
uniapp715666.8709.2755.6810.2
mpx538.8501.8562.6573.6595.2
chameleon1509.21672.41951.82232.42586.2

該項測試的結(jié)論為:
native > mpx > uniapp > chameleon > wepy2

結(jié)論分析:

  • 在大數(shù)據(jù)量場景下,框架之間基礎(chǔ)性能的差異會變得更加明顯,mpx和uniapp依然保持了接近原生的良好性能表現(xiàn),而chameleon和wepy2則產(chǎn)生了比較顯著的性能劣化。

局部更新耗時

我們在可用券數(shù)量為1000的情況下,點擊任意一張可用券觸發(fā)選中狀態(tài),以測試局部更新性能


toggleSelect(ms)
native2
wepy22.6
uniapp2.8
mpx2.2
chameleon2
mpvue289.6
kbone2440.8
taro next1975

該項測試的結(jié)論為:
native ≈ chameleon ≈ mpx ≈ wepy2 ≈ uniapp > mpvue > taro next > kbone

結(jié)論分析:

  • 可以看出所有使用了原生自定義組件進行組件化實現(xiàn)的框架局部更新耗時都極低,這足以證明小程序原生自定義組件的優(yōu)秀性和重要性;

  • mpvue由于使用了頁面更新,局部更新耗時顯著增加;

  • kbone和taro next由于遞歸動態(tài)渲染的性能開銷巨大,導(dǎo)致局部更新耗時同樣巨大。

setData調(diào)用

我們將proxySetData的count和size選項設(shè)置為true,開啟setData的次數(shù)和體積統(tǒng)計,重新構(gòu)建后按照以下流程執(zhí)行系列操作,并統(tǒng)計setData的調(diào)用次數(shù)和發(fā)送數(shù)據(jù)的體積。

操作流程如下:

  • 100逐級遞增可用券(0->500)

  • 切換至不可用券

  • 新增不可用券(1000)

  • 100逐級遞增可用券(500->1000)

  • 更新可用券(all)

  • 切換至可用券

  • 操作完成后我們使用getCount和getSize方法獲取累積的setData調(diào)用次數(shù)和數(shù)據(jù)體積,其中數(shù)據(jù)體積計算方式為JSON.stringify后按照utf-8編碼方式進行體積計算,統(tǒng)計結(jié)果為:


    countsize(KB)
    native14803
    wepy235141124
    mpvue162127
    uniapp14274
    mpx8261
    chameleon2515319
    kbone2210572
    taro next92321

    該項測試的結(jié)論為:
    mpx > uniapp > native > chameleon > wepy2 > taro next > mpvue > kbone

    結(jié)論分析:

    • mpx框架成功實現(xiàn)了理論上setData的最優(yōu);

    • uniapp由于缺失模板追蹤能力緊隨其后;

    • chameleon由于組件每次創(chuàng)建時都會進行一次不必要的setData,產(chǎn)生了大量無效setData調(diào)用,但是數(shù)據(jù)的發(fā)送本身經(jīng)過diff,在數(shù)據(jù)發(fā)送量上表現(xiàn)不錯;

    • wepy2的組件會在數(shù)據(jù)更新時調(diào)用setData發(fā)送已經(jīng)更新過的props數(shù)據(jù),因此也產(chǎn)生了大量無效調(diào)用,且diff精度不足,發(fā)送的數(shù)據(jù)量也較大;

    • taro next由于上層完全基于vue,在數(shù)據(jù)發(fā)送次數(shù)上控制到了9次,但由于需要發(fā)送大量的dom描述信息,數(shù)據(jù)發(fā)送量較大;

    • mpvue由于使用較長的數(shù)據(jù)路徑描述數(shù)據(jù)對應(yīng)的組件,也產(chǎn)生了較大的數(shù)據(jù)發(fā)送量;

    • kbone對于setData的調(diào)用控制得不是很好,在上層運行vue的情況依然進行了22次數(shù)據(jù)發(fā)送,且發(fā)送的數(shù)據(jù)量巨大,在此流程中達到了驚人的10MB。

    頁面渲染耗時(靜態(tài)測試)

    此處的頁面渲染耗時與前面描述的動態(tài)測試場景中相同,測試結(jié)果如下:


    頁面渲染耗時
    native70.4
    wepy286.6
    mpvue115.2
    uniapp69.6
    mpx66.6
    chameleon65
    kbone144.2
    taro next119.8

    該項測試的結(jié)論為:
    chameleon ≈ mpx ≈ uniapp ≈ native > wepy2 > mpvue ≈ taro next > kbone

    結(jié)論分析:

    • 除了kbone和taro next采用動態(tài)渲染耗時增加,mpvue使用頁面模板渲染性能稍差,其余框架的靜態(tài)頁面渲染表現(xiàn)都和原生差不多。

    結(jié)論

    綜合上述測試數(shù)據(jù),我們得到最終的小程序框架運行時性能排名為:
    mpx > uniapp > chameleon > wepy2 > mpvue > taro next > kbone

    一點私貨

    雖然kbone和taro next采用了動態(tài)渲染技術(shù)在性能表現(xiàn)上并不盡如人意,但是我依然認為這是很棒的技術(shù)方案。雖然本文從頭到位都在進行性能測試和對比,但性能并不是框架的全部,開發(fā)效率和高可用性仍然是框架的重心,開發(fā)效率相信是所有框架設(shè)計的初衷,但是高可用性卻在很大程度被忽視。從這個角度來說,kbone和taro next是非常成功的,不同于過去的轉(zhuǎn)譯思路,這種從抹平底層渲染環(huán)境的做法能夠使上層web框架完整運行,在框架可用性上帶來非常大的提升,非常適合于運營類簡單小程序的遷移和開發(fā)。

    我主導(dǎo)開發(fā)的mpx框架 https://github.com/didi/mpx 選擇了另一條道路解決可用性問題,那就是基于小程序原生語法能力進行增強,這樣既能避免轉(zhuǎn)譯web框架時帶來的不確定性和不穩(wěn)定性,同時也能帶來非常接近于原生的性能表現(xiàn),對于復(fù)雜業(yè)務(wù)小程序的開發(fā)者來說,非常推薦使用。在跨端輸出方面,mpx目前能夠完善支持業(yè)內(nèi)全部小程序平臺和web平臺的同構(gòu)輸出,滴滴內(nèi)部最重要最復(fù)雜的小程序——滴滴出行小程序完全基于mpx進行開發(fā),并利用框架提供的跨端能力對微信和支付寶入口進行同步業(yè)務(wù)迭代,大大提升了業(yè)務(wù)開發(fā)效率。

    ?? 看完三件事如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:

    點個「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點在看,都是耍流氓 -_-)

    關(guān)注我的博客 https://github.com/SHERlocked93/blog,讓我們成為長期關(guān)系

    關(guān)注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。

    在看點這里

    作者:董宏平(hiyuki),滴滴出行小程序負責人,mpx框架負責人及核心作者

    隨著小程序在商業(yè)上的巨大成功,小程序開發(fā)在國內(nèi)前端領(lǐng)域越來越受到重視,為了方便廣大開發(fā)者更好地進行小程序開發(fā),各類小程序框架也層出不窮,呈現(xiàn)出百花齊放的態(tài)勢。但是到目前為止,業(yè)內(nèi)一直沒有出現(xiàn)一份全面、詳細、客觀、公正的小程序框架測評報告,為小程序開發(fā)者在技術(shù)選型時提供參考。于是我便籌劃推出一系列文章,對業(yè)內(nèi)流行的小程序框架進行一次全方位的、客觀公正的測評,本文是系列文章的第一篇——運行時性能篇。

    在本文中,我們會對下列框架進行運行時性能測試(排名不分先后):

    • wepy2(https://github.com/Tencent/wepy) @2.0.0-alpha.20

    • uniapp(https://github.com/dcloudio/u...) @2.0.0-26120200226001

    • mpx(https://github.com/didi/mpx) @2.5.3

    • chameleon(https://github.com/didi/chame...) @1.0.5

    • mpvue(https://github.com/Meituan-Di...) @2.0.6

    • kbone(https://github.com/Tencent/kb...) @0.8.3

    • taro next(https://github.com/NervJS/taro) @3.0.0-alpha.5

    其中對于kbone和taro next均以vue作為業(yè)務(wù)框架進行測試。

    運行時性能的測試內(nèi)容包括以下幾個維度:

    • 框架運行時體積

    • 頁面渲染耗時

    • 頁面更新耗時

    • 局部更新耗時

    • setData調(diào)用次數(shù)

    • setData發(fā)送數(shù)據(jù)大小

    框架性能測試demo全部存放于https://github.com/hiyuki/mp-... 中,歡迎廣大開發(fā)者進行驗證糾錯及補全;

    測試方案

    為了使測試結(jié)果真實有效,我基于常見的業(yè)務(wù)場景構(gòu)建了兩種測試場景,分別是動態(tài)測試場景和靜態(tài)測試場景。

    動態(tài)測試場景

    動態(tài)測試中,視圖基于數(shù)據(jù)動態(tài)渲染,靜態(tài)節(jié)點較少,視圖更新耗時和setData調(diào)用情況是該測試場景中的主要測試點。

    動態(tài)測試demo模擬了實際業(yè)務(wù)中常見的長列表+多tab場景,該demo中存在兩份優(yōu)惠券列表數(shù)據(jù),一份為可用券數(shù)據(jù),另一份為不可用券數(shù)據(jù),其中同一時刻視圖中只會渲染展示其中一份數(shù)據(jù),可以在上方的操作區(qū)模擬對列表數(shù)據(jù)的各種操作及視圖展示切換(切tab)。

    動態(tài)測試demo

    動態(tài)測試demo

    在動態(tài)測試中,我在外部通過函數(shù)代理的方式在初始化之前將App、Page和Component構(gòu)造器進行代理,通過mixin的方式在Page的onLoad和Component的created鉤子中注入setData攔截邏輯,對所有頁面和組件的setData調(diào)用進行監(jiān)聽,并統(tǒng)計小程序的視圖更新耗時及setData調(diào)用情況。該測試方式能夠做到對框架代碼的零侵入,能夠跟蹤到小程序全量的setData行為并進行獨立的耗時計算,具有很強的普適性,代碼具體實現(xiàn)可以查看https://github.com/hiyuki/mp-...

    靜態(tài)測試場景

    靜態(tài)測試模擬業(yè)務(wù)中靜態(tài)頁面的場景,如運營活動和文章等頁面,頁面內(nèi)具備大量的靜態(tài)節(jié)點,而沒有數(shù)據(jù)動態(tài)渲染,初始ready耗時是該場景下測試的重心。

    靜態(tài)測試demo使用了我去年發(fā)表的一篇技術(shù)文章的html代碼進行小程序適配構(gòu)建,其中包含大量靜態(tài)節(jié)點及文本內(nèi)容。

    靜態(tài)測試demo

    靜態(tài)測試demo

    測試流程及數(shù)據(jù)

    以下所有耗時類的測試數(shù)據(jù)均為微信小程序中真機進行5次測試計算平均值得出,單位均為ms。Ios測試環(huán)境為手機型號iPhone 11,系統(tǒng)版本13.3.1,微信版本7.0.12,安卓測試環(huán)境為手機型號小米9,系統(tǒng)版本Android10,微信版本7.0.12。

    為了使數(shù)據(jù)展示不過于混亂復(fù)雜,文章中所列的數(shù)據(jù)以Ios的測試結(jié)果為主,安卓測試結(jié)論與Ios相符,整體耗時比Ios高3~4倍左右,所有的原始測試數(shù)據(jù)存放在https://github.com/hiyuki/mp-...

    由于transform-runtime引入的core-js會對框架的運行時體積和運行耗時帶來一定影響,且不是所有的框架都會在編譯時開啟transform-runtime,為了對齊測試環(huán)境,下述測試均在transform-runtime關(guān)閉時進行。

    框架運行時體積

    由于不是所有框架都能夠使用webpack-bundle-analyzer得到精確的包體積占用,這里我通過將各框架生成的demo項目體積減去native編寫的demo項目體積作為框架的運行時體積。


    demo總體積(KB)框架運行時體積(KB)
    native270
    wepy26639
    uniapp11487
    mpx7851
    chameleon136109
    mpvue10376
    kbone395368
    taro next183156

    該項測試的結(jié)論為:
    native > wepy2 > mpx > mpvue > uniapp > chameleon > taro next > kbone

    結(jié)論分析:

    • wepy2和mpx在框架運行時體積上控制得最好;

    • taro next和kbone由于動態(tài)渲染的特性,在dist中會生成遞歸渲染模板/組件,所以占用體積較大。

    頁面渲染耗時(動態(tài)測試)

    我們使用刷新頁面操作觸發(fā)頁面重新加載,對于大部分框架來說,頁面渲染耗時是從觸發(fā)刷新操作到頁面執(zhí)行onReady的耗時,但是對于像kbone和taro next這樣的動態(tài)渲染框架,頁面執(zhí)行onReady并不代表視圖真正渲染完成,為此,我們設(shè)定了一個特殊規(guī)則,在頁面onReady觸發(fā)的1000ms內(nèi),在沒有任何操作的情況下出現(xiàn)setData回調(diào)時,以最后觸發(fā)的setData回調(diào)作為頁面渲染完成時機來計算真實的頁面渲染耗時,測試結(jié)果如下:


    頁面渲染耗時
    native60.8
    wepy264
    uniapp56.4
    mpx52.6
    chameleon56.4
    mpvue117.8
    kbone98.6
    taro next89.6

    該項測試的耗時并不等同于真實的渲染耗時,由于小程序自身沒有提供performance api,真實渲染耗時無法通過js準確測試得出,不過從得出的數(shù)據(jù)來看該項數(shù)據(jù)依然具備一定的參考意義。

    該項測試的結(jié)論為:
    mpx ≈ chameleon ≈ uniapp ≈ native ≈ wepy2 > taro next ≈ kbone ≈ mpvue

    結(jié)論分析:

    • 由于mpvue全量在頁面進行渲染,kbone和taro next采用了動態(tài)渲染技術(shù),頁面渲染耗時較長,其余框架并無太大區(qū)別。

    頁面更新耗時(無后臺數(shù)據(jù))

    這里后臺數(shù)據(jù)的定義為data中存在但當前頁面渲染中未使用到的數(shù)據(jù),在這個demo場景下即為不可用券的數(shù)據(jù),當前會在不可用券為0的情況下,對可用券列表進行各種操作,并統(tǒng)計更新耗時。

    更新耗時的計算方式是從數(shù)據(jù)操作事件觸發(fā)開始到對應(yīng)的setData回調(diào)完成的耗時

    mpvue中使用了當前時間戳(new Date)作為超時依據(jù)對setData進行了超時時間為50ms的節(jié)流操作,該方式存在嚴重問題,當vue內(nèi)單次渲染同步流程執(zhí)行耗時超過50ms時,后續(xù)組件patch觸發(fā)的setData會突破這個節(jié)流限制,以50ms每次的頻率對setData進行高頻無效調(diào)用。在該性能測試demo中,當優(yōu)惠券數(shù)量超過500時,界面就會完全卡死。為了順利跑完整個測試流程,我對該問題進行了簡單修復(fù),使用setTimeout重寫了節(jié)流部分,確保在vue單次渲染流程同步執(zhí)行完畢后才會調(diào)用setData發(fā)送合并數(shù)據(jù),之后mpvue的所有性能測試都是基于這個patch版本來進行的,該patch版本存放在https://github.com/hiyuki/mp-...

    理論上來講native的性能在進行優(yōu)化的前提下一定是所有框架的天花板,但是在日常業(yè)務(wù)開發(fā)中我們可能無法對每一次setData都進行優(yōu)化,以下性能測試中所有的native數(shù)據(jù)均采用修改數(shù)據(jù)后全量發(fā)送的形式來實現(xiàn)。

    第一項測試我們使用新增可用券(100)操作將可用券數(shù)量由0逐級遞增到1000:


    1002003004005006007008009001000
    native84.669.871.67577.278.882.893.293.4105.4
    wepy2118.4168.6204.6246.4288.6347.8389.2434.2496539
    uniapp121.21009698.297.899.6104102.4109.4107.6
    mpx110.487.282.28380.679.686.690.689.296.4
    chameleon116.8115.4117119.6122125.2133.8133.2144.8145.6
    mpvue112.8121.2140169198.8234.2278.8318.4361.4408.2
    kbone556.4762.4991.61220.61468.81689.61933.22150.423892620.6
    taro next470604.6759.6902.41056.212281393.41536.21707.81867.2

    然后我們按順序逐項點擊刪除可用券(all) > 新增可用券(1000) > 更新可用券(1) > 更新可用券(all) > 刪除可用券(1):


    delete(all)add(1000)update(1)update(all)delete(1)
    native32.8295.692.292.283
    wepy256.8726.449.2535530.8
    uniapp43.6584.454.8144.8131.2
    mpx41.8489.652.6169.4165.6
    chameleon39765.695.6237.8144.8
    mpvue103.6669.4404.4414.8433.6
    kbone120.249782356.42419.42357
    taro next126.63930.61607.81788.62318.2

    該項測試中初期我update(all)的邏輯是循環(huán)對每個列表項進行更新,形如listData.forEach((item)=>{item.count++}),發(fā)現(xiàn)在chameleon框架中執(zhí)行界面會完全卡死,追蹤發(fā)現(xiàn)chameleon框架中沒有對setData進行異步合并處理,而是在數(shù)據(jù)變動時直接同步發(fā)送,這樣在數(shù)據(jù)量為1000的場景下用該方式進行更新會高頻觸發(fā)1000次setData,導(dǎo)致界面卡死;對此,我在chameleon框架的測試demo中,將update(all)的邏輯調(diào)整為深clone產(chǎn)生一份更新后的listData,再將其整體賦值到this.listData當中,以確保該項測試能夠正常進行。

    該項測試的結(jié)論為:
    native > mpx ≈ uniapp > chameleon > mpvue > wepy2 > taro next > kbone

    結(jié)論分析:

    • mpx和uniapp在框架內(nèi)部進行了完善的diff優(yōu)化,隨著數(shù)據(jù)量的增加,兩個框架的新增耗時沒有顯著上升;

    • wepy2會在數(shù)據(jù)變更時對props數(shù)據(jù)也進行setData,在該場景下造成了大量的無效性能損耗,導(dǎo)致性能表現(xiàn)不佳;

    • kbone和taro next采用了動態(tài)渲染方案,每次新增更新時會發(fā)送大量描述dom結(jié)構(gòu)的數(shù)據(jù),與此同時動態(tài)遞歸渲染的耗時也遠大于常規(guī)的靜態(tài)模板渲染,使得這兩個框架在所有的更新場景下耗時都遠大于其他框架。

    頁面更新耗時(有后臺數(shù)據(jù))

    刷新頁面后我們使用新增不可用券(1000)創(chuàng)建后臺數(shù)據(jù),觀察該操作是否會觸發(fā)setData并統(tǒng)計耗時


    back add(1000)
    native45.2
    wepy2174.6
    uniapp89.4
    mpx0
    chameleon142.6
    mpvue134
    kbone0
    taro next0

    mpx進行setData優(yōu)化時inspired by vue,使用了編譯時生成的渲染函數(shù)跟蹤模板數(shù)據(jù)依賴,在后臺數(shù)據(jù)變更時不會進行setData調(diào)用,而kbone和taro next采用了動態(tài)渲染技術(shù)模擬了web底層環(huán)境,在上層完整地運行了vue框架,也達到了同樣的效果。

    然后我們執(zhí)行和上面無后臺數(shù)據(jù)時相同的操作進行耗時統(tǒng)計,首先是遞增100:


    1002003004005006007008009001000
    native8869.871.280.879.484.489.893.299.6108
    wepy2121173.4213.6250298345.6383434.8476.8535.6
    uniapp135.4112.4110.6106.4109.6107.2114.4116118.8117.4
    mpx112.686.284.686.89087.291.288.892.493.4
    chameleon178.4178.2186.4184.6192.6203.8210217.6232.6236.8
    mpvue139151173.4194231.4258.8303.4340.4384.6429.4
    kbone559.8746.6980.61226.81450.61705.41927.22154.82367.82617
    taro next482.6626.2755909.610851233.213841568.61740.61883.8

    然后按下表操作順序逐項點擊統(tǒng)計


    delete(all)add(1000)update(1)update(all)delete(1)
    native43.4299.889.28987.2
    wepy243.2762.450533522.4
    uniapp57.8589.862.6160.6154.4
    mpx45.8490.852.8167166
    chameleon93.8837184.6318220.8
    mpvue124.8696.2423.4419430.6
    kbone121.44978.22331.22448.42348
    taro next129.83947.21610.41813.82290.2

    該項測試的結(jié)論為:
    native > mpx > uniapp > chameleon > mpvue > wepy2 > taro next > kbone

    結(jié)論分析:

    • 具備模板數(shù)據(jù)跟蹤能力的三個框架mpx,kbone和taro next在有后臺數(shù)據(jù)場景下耗時并沒有顯著增加;

    • wepy2當中的diff精度不足,耗時也沒有產(chǎn)生明顯變化;

    • 其余框架由于每次更新都會對后臺數(shù)據(jù)進行deep diff,耗時都產(chǎn)生了一定提升。

    頁面更新耗時(大數(shù)據(jù)量場景)

    由于mpvue和taro next的渲染全部在頁面中進行,而kbone的渲染方案會額外新增大量的自定義組件,這三個框架都會在優(yōu)惠券數(shù)量達到2000時崩潰白屏,我們排除了這三個框架對其余框架進行大數(shù)據(jù)量場景下的頁面更新耗時測試

    首先還是在無后臺數(shù)據(jù)場景下使用新增可用券(1000)將可用券數(shù)量遞增至5000:


    10002000300040005000
    native332.6350412.6498.2569.4
    wepy2970.21531.42015.22890.63364.2
    uniapp655.2593.4655675.6718.8
    mpx532.2496548.6564601.8
    chameleon805.4839.6952.81086.61291.8

    然后點擊新增不可用券(5000)將后臺數(shù)據(jù)量增加至5000,再測試可用券數(shù)量遞增至5000的耗時:


    back add(5000)
    native117.4
    wepy2511.6
    uniapp285
    mpx0
    chameleon824

    10002000300040005000
    native349.8348.4430.4497594.8
    wepy2112818722470.43263.44075.8
    uniapp715666.8709.2755.6810.2
    mpx538.8501.8562.6573.6595.2
    chameleon1509.21672.41951.82232.42586.2

    該項測試的結(jié)論為:
    native > mpx > uniapp > chameleon > wepy2

    結(jié)論分析:

    • 在大數(shù)據(jù)量場景下,框架之間基礎(chǔ)性能的差異會變得更加明顯,mpx和uniapp依然保持了接近原生的良好性能表現(xiàn),而chameleon和wepy2則產(chǎn)生了比較顯著的性能劣化。

    局部更新耗時

    我們在可用券數(shù)量為1000的情況下,點擊任意一張可用券觸發(fā)選中狀態(tài),以測試局部更新性能


    toggleSelect(ms)
    native2
    wepy22.6
    uniapp2.8
    mpx2.2
    chameleon2
    mpvue289.6
    kbone2440.8
    taro next1975

    該項測試的結(jié)論為:
    native ≈ chameleon ≈ mpx ≈ wepy2 ≈ uniapp > mpvue > taro next > kbone

    結(jié)論分析:

    • 可以看出所有使用了原生自定義組件進行組件化實現(xiàn)的框架局部更新耗時都極低,這足以證明小程序原生自定義組件的優(yōu)秀性和重要性;

    • mpvue由于使用了頁面更新,局部更新耗時顯著增加;

    • kbone和taro next由于遞歸動態(tài)渲染的性能開銷巨大,導(dǎo)致局部更新耗時同樣巨大。

    setData調(diào)用

    我們將proxySetData的count和size選項設(shè)置為true,開啟setData的次數(shù)和體積統(tǒng)計,重新構(gòu)建后按照以下流程執(zhí)行系列操作,并統(tǒng)計setData的調(diào)用次數(shù)和發(fā)送數(shù)據(jù)的體積。

    操作流程如下:

  • 100逐級遞增可用券(0->500)

  • 切換至不可用券

  • 新增不可用券(1000)

  • 100逐級遞增可用券(500->1000)

  • 更新可用券(all)

  • 切換至可用券

  • 操作完成后我們使用getCount和getSize方法獲取累積的setData調(diào)用次數(shù)和數(shù)據(jù)體積,其中數(shù)據(jù)體積計算方式為JSON.stringify后按照utf-8編碼方式進行體積計算,統(tǒng)計結(jié)果為:


    countsize(KB)
    native14803
    wepy235141124
    mpvue162127
    uniapp14274
    mpx8261
    chameleon2515319
    kbone2210572
    taro next92321

    該項測試的結(jié)論為:
    mpx > uniapp > native > chameleon > wepy2 > taro next > mpvue > kbone

    結(jié)論分析:

    • mpx框架成功實現(xiàn)了理論上setData的最優(yōu);

    • uniapp由于缺失模板追蹤能力緊隨其后;

    • chameleon由于組件每次創(chuàng)建時都會進行一次不必要的setData,產(chǎn)生了大量無效setData調(diào)用,但是數(shù)據(jù)的發(fā)送本身經(jīng)過diff,在數(shù)據(jù)發(fā)送量上表現(xiàn)不錯;

    • wepy2的組件會在數(shù)據(jù)更新時調(diào)用setData發(fā)送已經(jīng)更新過的props數(shù)據(jù),因此也產(chǎn)生了大量無效調(diào)用,且diff精度不足,發(fā)送的數(shù)據(jù)量也較大;

    • taro next由于上層完全基于vue,在數(shù)據(jù)發(fā)送次數(shù)上控制到了9次,但由于需要發(fā)送大量的dom描述信息,數(shù)據(jù)發(fā)送量較大;

    • mpvue由于使用較長的數(shù)據(jù)路徑描述數(shù)據(jù)對應(yīng)的組件,也產(chǎn)生了較大的數(shù)據(jù)發(fā)送量;

    • kbone對于setData的調(diào)用控制得不是很好,在上層運行vue的情況依然進行了22次數(shù)據(jù)發(fā)送,且發(fā)送的數(shù)據(jù)量巨大,在此流程中達到了驚人的10MB。

    頁面渲染耗時(靜態(tài)測試)

    此處的頁面渲染耗時與前面描述的動態(tài)測試場景中相同,測試結(jié)果如下:


    頁面渲染耗時
    native70.4
    wepy286.6
    mpvue115.2
    uniapp69.6
    mpx66.6
    chameleon65
    kbone144.2
    taro next119.8

    該項測試的結(jié)論為:
    chameleon ≈ mpx ≈ uniapp ≈ native > wepy2 > mpvue ≈ taro next > kbone

    結(jié)論分析:

    • 除了kbone和taro next采用動態(tài)渲染耗時增加,mpvue使用頁面模板渲染性能稍差,其余框架的靜態(tài)頁面渲染表現(xiàn)都和原生差不多。

    結(jié)論

    綜合上述測試數(shù)據(jù),我們得到最終的小程序框架運行時性能排名為:
    mpx > uniapp > chameleon > wepy2 > mpvue > taro next > kbone

    一點私貨

    雖然kbone和taro next采用了動態(tài)渲染技術(shù)在性能表現(xiàn)上并不盡如人意,但是我依然認為這是很棒的技術(shù)方案。雖然本文從頭到位都在進行性能測試和對比,但性能并不是框架的全部,開發(fā)效率和高可用性仍然是框架的重心,開發(fā)效率相信是所有框架設(shè)計的初衷,但是高可用性卻在很大程度被忽視。從這個角度來說,kbone和taro next是非常成功的,不同于過去的轉(zhuǎn)譯思路,這種從抹平底層渲染環(huán)境的做法能夠使上層web框架完整運行,在框架可用性上帶來非常大的提升,非常適合于運營類簡單小程序的遷移和開發(fā)。

    我主導(dǎo)開發(fā)的mpx框架 https://github.com/didi/mpx 選擇了另一條道路解決可用性問題,那就是基于小程序原生語法能力進行增強,這樣既能避免轉(zhuǎn)譯web框架時帶來的不確定性和不穩(wěn)定性,同時也能帶來非常接近于原生的性能表現(xiàn),對于復(fù)雜業(yè)務(wù)小程序的開發(fā)者來說,非常推薦使用。在跨端輸出方面,mpx目前能夠完善支持業(yè)內(nèi)全部小程序平臺和web平臺的同構(gòu)輸出,滴滴內(nèi)部最重要最復(fù)雜的小程序——滴滴出行小程序完全基于mpx進行開發(fā),并利用框架提供的跨端能力對微信和支付寶入口進行同步業(yè)務(wù)迭代,大大提升了業(yè)務(wù)開發(fā)效率。

    輕點在看,支持作者??

    總結(jié)

    以上是生活随笔為你收集整理的七大热门小程序框架横评,谁是性能之王的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。