與之相隨,小程序的開發(fā)生態(tài)也在蓬勃發(fā)展,從最初的微信原生開發(fā),到wepy
、mpvue
、taro
、uni-app
等框架依次出現(xiàn),從刀耕火種演進為現(xiàn)代化開發(fā),生態(tài)越來越豐富。
選擇多了,問題也就來了,開發(fā)小程序,該用原生還是選擇三方框架?
首先,微信原生開發(fā)的槽點大多集中如下:
原生開發(fā)對Node、預(yù)編譯器、webpack支持不好,影響開發(fā)效率和工程構(gòu)建流程
微信定義了一個不倫不類的語法,不如正經(jīng)學(xué)vue、react,學(xué)會了全端通用,而不是只為微信小程序
vue/react生態(tài)里有太多周邊工具,可以提高開發(fā)效率,比如ide、校驗器、三方庫。。。
微信那個ide和專業(yè)編輯器相比實在不好用
同時,開發(fā)者對三方框架,又總是有各種顧慮:
怕性能不如原生
怕有些功能框架實現(xiàn)不了,只能用原生
怕框架不穩(wěn)定,跳到坑里
以及諸多三方框架,到底該用哪個
面對如此糾結(jié)的場景,不少熱心開發(fā)者發(fā)布評測文章分享經(jīng)驗,但感覺眾說紛紜,過期信息太多。缺少一份非常專業(yè)的、深度的,或者按如今流行的話來講,“硬核的”評測報告。
做評測報告這件事,不同于泛泛經(jīng)驗分享,其實非?;ㄙM時間。它需要:
你必須成為每一個框架的專業(yè)使用人員,而不是淺淺的了解一下這些框架
真實的動手寫多個平臺的測試例,比較各個平臺的功能、性能,了解他們的社區(qū)情況、技術(shù)服務(wù)情況
你要有長期跟蹤和更新報告的能力,避免半年后淪為過期信息
換言之:評測要想真,功夫得做深!
uni-app
團隊花費2個周時間完成本報告,并堅持每個季度更新一次本評測報告。目前更新時間為2019年5月。
本文從面向用戶、面向開發(fā)者
兩大維度七大細項,對微信原生及主流的wepy
、mpvue
、taro
、uni-app
開發(fā)框架進行橫向?qū)Ρ龋Mo開發(fā)者在小程序框架選型時提供一種參考思路。本文基于各框架官網(wǎng)可采集到的公開數(shù)據(jù)及真實測試數(shù)據(jù),希望客觀公正地評價各個框架的現(xiàn)狀和優(yōu)劣。但宥于利益相關(guān),本文的觀點很可能是帶有偏向性的,大家可以帶著批判的眼光來看待,如發(fā)現(xiàn)本文中有任何評測失真,歡迎在這里報 issuse 。
面向用戶、面向開發(fā)者
維度,具體包括:
用戶:提供完整的業(yè)務(wù)實現(xiàn),并保證高性能體驗
開發(fā)者:平緩的學(xué)習(xí)曲線、現(xiàn)代開發(fā)體驗(工程化)、高效的社區(qū)支持、活躍的開發(fā)迭代、多端復(fù)用
1. 用戶 1.1 功能實現(xiàn) 軟件開發(fā),首要目標是向用戶提供完整、閉環(huán)的業(yè)務(wù)功能。
在web開發(fā)中,如果vue、react等框架的使用,造成開發(fā)者無法操作瀏覽器提供的所有api,那這樣的框架肯定是不成熟的。小程序開發(fā)也一樣,任何開發(fā)框架,都不能限制底層的api調(diào)用。
而各種業(yè)務(wù)功能底層依賴微信暴漏的組件和接口(微信官網(wǎng)介紹的組件和 API 規(guī)范,也即微信原生API),三方框架是基于微信原生進行的二次封裝,開發(fā)者此時常會有個疑問:小程序在不斷的迭代升級,如果某項業(yè)務(wù)依賴于最新的小程序API,但三方框架尚未封裝,該怎么辦?
實際上就像web開發(fā)的vue、react一樣,瀏覽器出了一個新API,并不會涉及vue、react的升級。本評測里的所有框架,都不會限制開發(fā)者調(diào)用底層能力。這里詳細解釋下原因:
wepy:未對小程序API作二次封裝,API依然使用微信原生的,框架與微信小程序是否新增API無關(guān)
mpvue:支持微信的所有原生組件和api,無限制。同時框架封裝了自己的跨端API,使用方式類似mpvue.request()
taro:支持微信的所有原生組件和api,無限制。同時框架封裝了自己的跨端API,使用方式類似Taro.request()
,支持Taro 代碼與小程序代碼混寫 ,可通過混寫的方式調(diào)用框架尚未封裝的小程序新增API
uni-app:支持微信的所有原生組件和api,無限制。在跨端方面,即便仍然使用微信原生的組件和API,也可以直接跨端編譯到App、H5、以及支付寶百度頭條等小程序。但為了管理清晰,推薦使用uni封裝的API,類似uni.request()
。同時支持條件編譯 ,可在條件編譯代碼塊中,隨意調(diào)用各個平臺新增的API及組件
注:以上順序,按各個框架的誕生順序排序,下同。
故,三方框架均可調(diào)用所有小程序API,完成用戶的業(yè)務(wù)需求,這個維度各框架是無差別的。
然而有差別的,是性能體驗。
1.2 性能體驗 三方框架,內(nèi)部大多做了層層封裝,這些封裝是否會增加運行負載,導(dǎo)致性能下降?尤其是與原生微信小程序開發(fā)相比性能怎么樣,這是大家普遍關(guān)心的問題。
為客觀的進行對比,我們特意搭建了一個測試模型,詳細如下:
開發(fā)內(nèi)容:開發(fā)一個仿微博小程序首頁的復(fù)雜長列表,支持下拉刷新、上拉翻頁、點贊。
界面如下:
開發(fā)版本:一共開發(fā)了5個版本,包括微信原生版、wepy版、mpvue版、taro版、uni-app版,按照官網(wǎng)指引通過cli
方式默認安裝。
測試代碼開源(Github倉庫地址:https://github.com/dcloudio/test-framework ), Tips:若有同學(xué)覺得測試代碼寫法欠妥,歡迎提交 PR 或 Issus
測試機型:紅米 Redmi 6 Pro、MIUI 10.2.2.0 穩(wěn)定版(最新版)、微信版本 7.0.3(最新版)
測試環(huán)境:每個框架開始測試前,殺掉各App進程、清空內(nèi)存,保證測試機環(huán)境基本一致;每次從本地讀取靜態(tài)數(shù)據(jù),屏蔽網(wǎng)絡(luò)差異。
我們以上述仿微博小程序為例,測試2個容易出性能問題的點:長列表加載、大量點贊組件的響應(yīng)。
1.2.1 長列表加載 仿微博的列表是一個包含很多組件的列表,這種復(fù)雜列表對性能的壓力更大,很適合做性能測試。
從觸發(fā)上拉加載到數(shù)據(jù)更新、頁面渲染完成,需要準確計時。人眼視覺計時肯定不行,我們采用程序埋點的方式,制定了如下計時時機:
Tips:setData
回調(diào)函數(shù)開頭可認為是頁面渲染完成的時間,是因為微信setData
定義如下(微信規(guī)范 ):
測試方式:從頁面空列表開始,通過程序自動觸發(fā)上拉加載,每次新增20條列表,記錄單次耗時;固定間隔連續(xù)觸發(fā) N 次上拉加載,使得頁面達到 20*N 條列表,計算這 N 次觸發(fā)上拉到渲染完成的平均耗時。
測試結(jié)果如下:
說明:以400條微博列表為例,從頁面空列表開始,每隔1秒觸發(fā)一次上拉加載(新增20條微博),記錄單次耗時,觸發(fā)20次后停止(頁面達到400條微博),計算這20次的平均耗時,結(jié)果微信原生在這20次 觸發(fā)上拉 -> 渲染完成
的平均耗時為876毫秒,最快的uni-app
是741毫秒,最慢的mpvue
是4493毫秒
大家初看這個數(shù)據(jù),可能比較疑惑,別急,下方有詳細說明
說明1:為何 mpvue/wepy 測試數(shù)據(jù)不完整?
mpvue
、wepy
誕生之初,微信小程序尚不支持自定義組件 ,無法進行組件化開發(fā);mpvue
、wepy
為解決這個問題,將用戶編寫的Vue
組件,編譯為WXML
中的模板(template) ,變相實現(xiàn)了組件化開發(fā)能力,提高代碼復(fù)用性,這在當(dāng)時的技術(shù)條件下是很棒的技術(shù)方案。
但如此方案,在頁面復(fù)雜、組件較多的時,會大量增加頁面 dom 節(jié)點數(shù)量,甚至超出微信的 dom 節(jié)點數(shù)限制。我們在 紅米手機(Redmi 6 Pro)上實測,頁面組件超過500個時,mpvue
、wepy
實現(xiàn)的仿微博App就會報出如下異常,并停止渲染,故這兩個測試框架在組件較多時,測試數(shù)據(jù)不完整。這也就意味著,當(dāng)頁面組件太多時,無法使用這2個框架。
dom limit exceeded please check if there's any mistake you've made
Tips1:wepy
官網(wǎng)的CHANGELOG ,提到 v1.7.2 測試版本添加了對小程序原生組件的支持,實測坑很多,因為是測試版,官方在 issue 中也表示不推薦使用;按照官網(wǎng)文檔,默認安裝的 v1.7.3 正式版本并不支持原生組件
Tips2:wepy
在400條列表以內(nèi),為何性能高于微信原生框架,這個跟自定義組件管理開銷及業(yè)務(wù)場景有關(guān)(wepy
編譯為模板,不涉及組件創(chuàng)建及管理開銷),后續(xù)對微博點贊,涉及組件數(shù)據(jù)傳遞時,微信原生框架的性能優(yōu)勢就提現(xiàn)出來了,詳見下方測試數(shù)據(jù)。
說明2:為什么測試數(shù)據(jù)顯示uni-app 會比微信原生框架的性能略好呢?
其實,在頁面上有200條記錄(200個組件)時,taro
性能數(shù)據(jù)也比微信原生框架更好。
微信原生框架耗時主要在setData
調(diào)用上,開發(fā)者若不單獨優(yōu)化,則每次都會傳遞大量數(shù)據(jù);而uni-app
、taro
都在調(diào)用setData
之前自動做diff
計算,每次僅傳遞變動的數(shù)據(jù)。
例如當(dāng)前頁面有20條數(shù)據(jù),觸發(fā)上拉加載時,會新加載20條數(shù)據(jù),此時原生框架通過如下代碼測試時,setData
會傳輸40條數(shù)據(jù)
data: {
listData: []
},onReachBottom () { //上拉加載 let listData = this.data.listData;
listData.push(...Api.getNews());//新增數(shù)據(jù)
this.setData({
listData
}) //全量數(shù)據(jù),發(fā)送數(shù)據(jù)到視圖層
}復(fù)制代碼
開發(fā)者使用微信原生框架,完全可以自己優(yōu)化,精簡傳遞數(shù)據(jù),比如修改如下:
data: { listData: []
},
onReachBottom() { //上拉加載
// 通過長度獲取下一次渲染的索引
let index = this .data.listData.length; let newData = {}; //新變更數(shù)據(jù)
Api.getNews().forEach((item) => {
newData['listData[' + (index++) + ']' ] = item //賦值,索引遞增
})
this .setData(newData) //增量數(shù)據(jù),發(fā)送數(shù)據(jù)到視圖層 }復(fù)制代碼
經(jīng)過如上優(yōu)化修改后,再次測試,微信原生框架性能數(shù)據(jù)如下:
從測試結(jié)果可看出,經(jīng)過開發(fā)者手動優(yōu)化,微信原生框架可達到更好的性能,但 uni-app
、taro
相比微信原生,性能差距并不大。
這個結(jié)果,和web開發(fā)類似,web開發(fā)也有原生js開發(fā)、vue、react框架等情況。如果不做特殊優(yōu)化,原生js寫的網(wǎng)頁,性能經(jīng)常還不如vue、react框架的性能。
也恰恰是因為Vue
、react
框架的優(yōu)秀,性能好,開發(fā)體驗好,所以原生js開發(fā)已經(jīng)逐漸減少使用了。
復(fù)雜長列表加載下一頁評測結(jié)論:微信原生開發(fā)手工優(yōu)化
,uni-app
>微信原生開發(fā)未手工優(yōu)化
,taro
> wepy
> mpvue
Tips:有人以為uni-app和mpvue是一樣的,早期uni-app確實使用過mpvue,但后來因為性能和vue語法支持度問題已經(jīng)重新開發(fā)了。
1.2.2 點贊組件響應(yīng)速度 長列表中的某個組件,比如點贊組件,點擊時是否能及時的修改未贊和已贊狀態(tài)?是這項測試的評測點。
測試方式:
在紅米手機(Redmi 6 Pro)上進行多次測試,求其平均值,結(jié)果如下:
說明:也就是在列表數(shù)量為400時,微信原生開發(fā)的應(yīng)用,點贊按鈕從點擊到狀態(tài)變化需要111毫秒。
測試結(jié)果數(shù)據(jù)說明:
組件數(shù)據(jù)更新性能測評:微信原生開發(fā)
,uni-app
,taro
> wepy
> mpvue
綜上,本性能測試做了2個測試,長列表加載和組件狀態(tài)更新,綜合2個實驗,結(jié)論如下:
微信原生開發(fā)手工優(yōu)化
,uni-app
>微信原生開發(fā)未手工優(yōu)化
,taro
> wepy
> mpvue
2.開發(fā)者 在滿足用戶業(yè)務(wù)需求的前提下,我們談?wù)勯_發(fā)者的需求,從如下幾個維度比較:
平緩的學(xué)習(xí)曲線:簡單易學(xué),最好能復(fù)用現(xiàn)有技術(shù)棧,豐富的學(xué)習(xí)資料
高效的開發(fā)體驗:現(xiàn)代前端開發(fā)流程、工程化支持
高效的社區(qū)支持:遇到問題,可很快的尋求到幫助
活躍的開發(fā)迭代:框架處于積極更新升級狀態(tài),無需擔(dān)心停更
2.1 平緩的學(xué)習(xí)曲線 2.1.1 DSL語法支持 選擇開發(fā)團隊熟悉的、能快速上手的DSL,是團隊框架選型的基本點。
首先微信原生的開發(fā)語法,既像React
,又像Vue
,有點不倫不類,對于開發(fā)者來說,等于又要學(xué)習(xí)一套新的語法,大幅提升了學(xué)習(xí)成本,這一直被大家所詬病。
其它開發(fā)框架基本都遵循React、Vue(類Vue)語法,其主要目的:復(fù)用工程師的現(xiàn)有技術(shù)棧,降低學(xué)習(xí)成本。此時,框架對于原框架(React/Vue)語法的支持度就是一個重要的衡量標準,如果支持度較低、和原框架語法差異較大,則開發(fā)者無異于要學(xué)習(xí)一門新的框架,成本太高。
實際開發(fā)中發(fā)現(xiàn),各個開發(fā)框架,都沒有完全實現(xiàn)Vue
、React
在web上的所有語法:
wepy
開發(fā)風(fēng)格接近于 Vue.js
,屬于類Vue
實現(xiàn),相對微信原生開發(fā)算前進了一大步,但相比完整Vue
語法還有較大差距,開發(fā)時需要單獨學(xué)習(xí)它的規(guī)則;
mpvue
、uni-app
框架基于 Vue.js
核心,通過修改 Vue.js
的 runtime
和 compiler
,實現(xiàn)了在小程序端的運行。mpvue
支持的Vue語法略少,uni-app
則基本支持絕大多數(shù)vue語法,如filter
、復(fù)雜 JavaScript
表達式等;
taro
對于 JSX
的語法支持度,也達到了絕大多數(shù)都支持的完善程度。
DSL語法支持評測:taro
,uni-app
> mpvue
> wepy
> 微信原生
2.1.2 學(xué)習(xí)資料完善度 官方文檔、問題搜索、示例demo的完備度方面:
微信原生:文檔豐富,API搜索準確,官方有示例demo,支持官網(wǎng)上調(diào)起微信開發(fā)者工具,預(yù)覽運行效果 詳見
wepy:文檔只有2頁,沒有搜索,組件API等文檔都直接看微信的文檔。沒有提供示例demo,很多配置需要靠猜。詳見
mpvue:文檔較少,但其概念不復(fù)雜,組件API等文檔都直接看微信的文檔,學(xué)習(xí)難度低。問題搜索效果一般。沒有提供示例demo。詳見
taro:基礎(chǔ)文檔完整,具體使用問題資源較少,問題搜索效果一般,示例demo只包含基礎(chǔ)功能,僅發(fā)布了微信一端。詳見
uni-app:基礎(chǔ)文檔和各種使用專題內(nèi)容豐富,問題搜索效果較好,示例demo功能完備,并發(fā)布為7端上線。詳見
教學(xué)課程方面:
學(xué)習(xí)資料完善度評測:微信原生 > uni-app
> mpvue
, taro
> wepy
2.2 現(xiàn)代前端開發(fā)體驗 開發(fā)體驗層面,處于明顯劣勢的是微信原生開發(fā),主要差距在于:
框架開發(fā)提供了精簡的代碼組織(微信原生開發(fā),一個Page由4個文件構(gòu)成,寫個代碼要開的標簽卡太多)
框架開發(fā)提供了更強大的組件化能力
框架開發(fā)提供了應(yīng)用狀態(tài)管理(類Vuex/Redux/Mobx等)
框架開發(fā)能靈活支持各種 Sass 等 預(yù)處理器
框架開發(fā)可提供完整的 ES Next 語法支持
框架開發(fā)方便自定義構(gòu)建策略
其它小程序開發(fā)框架均支持cli
模式,可以在主流前端工具中開發(fā),且基本都帶有d.ts的語法提示庫。
由于mpvue
、uni-app
、taro
直接支持vue
、react
語法,配套的ide工具鏈較豐富,著色、校驗、格式化完善;wepy
要弱一些,有部分三方維護的vscode插件。
好的開發(fā)工具,絕對可以大幅提升開發(fā)體驗,這個維度上,明顯高出一截的框架是uni-app
,其出品公司同時也是HBuilder的出品公司,DCloud.io 。HBuilder是四大主流前端開發(fā)工具(可對比百度指數(shù) ),其為uni-app
做了很多優(yōu)化,故uni-app
的開發(fā)效率、易用性非其他框架可及。
開發(fā)體驗維度,對比結(jié)果:uni-app
> taro
,mpvue
> wepy
> 微信原生
這里可以輸出一個結(jié)論:如果你需要工程化能力,那就直接忘了微信原生開發(fā)吧。
2.3 高效的社區(qū)支持 學(xué)習(xí)、開發(fā)難免遇到問題,官方技術(shù)支持和社區(qū)活躍度很重要。
本次評測demo開發(fā)期間,我們的同學(xué)(同時掌握vue和react),在學(xué)習(xí)研究各個多端框架時,切實感受到由于語法、學(xué)習(xí)資料、社區(qū)的差異帶來的學(xué)習(xí)門檻,吐出了很多槽。
綜合評估,本項評測結(jié)論:微信原生
, uni-app
> taro
> mpvue
> wepy
2.4 活躍的開發(fā)迭代 開發(fā)者必須關(guān)心一個問題:該項目是否有人長期維護?
這個問題可以通過github commits 頻次、產(chǎn)品更新日志(changelog)、百度搜索指數(shù)等指標來衡量和對比。
github commits 頻次
我們采集2019年4月份(時間為4.1 ~ 4.30),每個項目在github上的master分支有commit的天數(shù),結(jié)果如下:
Tips:
從 commit 的記錄來看,taro
、uni-app
處于更新比較活躍的狀態(tài),wepy
、mpvue
則相對疲軟,呈現(xiàn)無人維護之態(tài)。
產(chǎn)品更新日志
通過瀏覽產(chǎn)品更新日志,可確認產(chǎn)品是否在積極迭代、增加新功能、修復(fù)用戶bug。
我們分別查看各框架官方鏈接的更新日志(CHANGELOG),下方是鏈接地址:
通過產(chǎn)品更新日志對比,微信原生、taro
、uni-app
三者更新頻繁,bug修復(fù)、新功能補充都處于比較緊湊的狀態(tài);而mpvue
、wepy
則已有長時間沒有版本發(fā)布,wepy
甚至有將近1年時間未發(fā)布正式版本,開發(fā)者選型需謹慎。
2.5 多端復(fù)用 隨著微信小程序的火爆,支付寶、百度、字節(jié)跳動等公司也先后進入小程序領(lǐng)域,這些公司個個日活過億,坐擁海量用戶,企業(yè)主希望將自己的業(yè)務(wù)觸達每個用戶,不管這個用戶在哪個小程序中。
需求轉(zhuǎn)接到程序員這里,程序員怎么辦?難道真的每個平臺到處搬磚嗎?此時,一套代碼、多端發(fā)布就成為很多程序員的夢想,小程序跨端框架應(yīng)運而生。
現(xiàn)實真能如此理想嗎?每個跨端框架能否真的像官網(wǎng)宣傳的那樣,實現(xiàn)開發(fā)一次,發(fā)布到所有小程序平臺?甚至和H5平臺復(fù)用代碼?
我們用事實說話,依然使用上述仿微博App ,依次發(fā)布到各平臺,驗證每個框架在各端的兼容性,結(jié)果如下:
測試結(jié)果說明:
通過這個簡單的例子可以看出,跨端支持度測評結(jié)論: uni-app
,taro
> mpvue
> 原生微信小程序
、wepy
但是僅有上面的測試還不全面,實際業(yè)務(wù)要比這個測試例復(fù)雜很多。但我們沒法開發(fā)很多復(fù)雜業(yè)務(wù)做評測,所以還需要再對照各家文檔補充一些信息。 由于每個框架的文檔中都描述了各種組件和API的跨端支持程度。我們過了幾家的文檔,發(fā)現(xiàn)各家基本是以微信小程序為基線,然后把各種組件和API在其他端實現(xiàn)了一遍:
跨端框架,一方面要考慮框架提供的通用api跨端支持,同時還要考慮不同端的特色差異如何兼容。畢竟每個端都會有自己的特色,不可能完全一致。
跨端框架,還涉及一個ui框架的跨端問題,評測結(jié)果如下:
最后補充跨端案例:
綜合以上信息,本項的最終評測結(jié)論:uni-app
> taro
> mpvue
> 原生微信小程序
、wepy
這里可以輸出一個結(jié)論,如果有多端發(fā)布需求,微信原生開發(fā)、wepy
這兩種方式可以直接排除了。
結(jié)語 真實客觀的永遠是實驗和數(shù)據(jù),而不是結(jié)論。不同需求的開發(fā)者,可以根據(jù)上述實驗數(shù)據(jù),自行得出自己的選型結(jié)論。
但作為一篇完整的評測,我們也必須提供一份總結(jié),雖然它可能加入了我們的主觀感受:
如果你只開發(fā)微信小程序,不做多端,那么使用uni-app
、taro
是更優(yōu)的選擇,他們相當(dāng)于web世界的vue和react,有了這些工具,不再需要使用原生wxml開發(fā)。
如果你開發(fā)多端,uni-app
和taro
都可以,可根據(jù)自己熟悉的技術(shù)棧選擇,相對而言uni-app
的多端成熟度更高一些。