使用uni-app開發(fā)小程序,比直接原生開發(fā)小程序好在哪里(uni app開發(fā)小程序)
小程序原生開發(fā)有不少槽點(diǎn):
- 原生wxml開發(fā)對(duì)Node、預(yù)編譯器、webpack支持不好,影響開發(fā)效率和工程構(gòu)建流程。所以大公司都會(huì)用框架開發(fā)
- 微信定義的這套語(yǔ)法,wxml、wxs,以及wx:if等語(yǔ)法,私有化太強(qiáng)。不如正經(jīng)學(xué)vue,學(xué)會(huì)了全端通用,而不是只為微信小程序
- vue生態(tài)里有太多周邊工具,可以提高開發(fā)效率,比如ide、校驗(yàn)器、三方庫(kù)。。。而微信的開發(fā)者工具和專業(yè)編輯器相比實(shí)在不好用,個(gè)性化設(shè)置也非常少
作為前端工程師,除了微信小程序,還要開發(fā)web、其他小程序甚至App,人們不喜歡來回切換開發(fā)工具和變更語(yǔ)法思考方式。
uni-app自然可以解決這些問題,但開發(fā)者又經(jīng)常有些顧慮:
- 怕使用uni-app后,微信小程序里有的功能無法實(shí)現(xiàn),受制于uni-app的更新
- 怕性能不如原生WXML
- 怕框架不成熟,跳到坑里
- 擔(dān)心社區(qū)生態(tài)不完善
本文從開發(fā)者關(guān)心的功能、性能、學(xué)習(xí)門檻、開發(fā)體驗(yàn)、生態(tài)、可擴(kuò)展性等維度,逐個(gè)分析對(duì)比,給予說明。
1.功能實(shí)現(xiàn)
開發(fā)者最常問的問題:如果小程序迭代升級(jí),新增了一批API,但uni-app框架未及時(shí)更新,該怎么辦?
其實(shí)這是誤解,uni-app不限制底層API 調(diào)用;在小程序端,uni-app支持直接編寫微信原生代碼。
類比傳統(tǒng)web開發(fā),如果vue、react等框架的使用,造成開發(fā)者無法操作瀏覽器提供的所有api,那這樣的框架肯定是不成熟的。小程序開發(fā)也一樣,uni-app框架中,同樣可調(diào)用微信提供的所有原生代碼。
故如果存在某些API(平臺(tái)特有或新增API),uni-app尚未封裝,開發(fā)者可直接在uni-app中編寫微信原生API,即wx.開頭的各種API。
舉個(gè)例子,目前uni-app雖然尚未封裝跨平臺(tái)的廣告(ad)組件,但開發(fā)者在小程序端依然可以使用微信<ad>組件來展現(xiàn)廣告,代碼示例如下:
<view> <view class=”title”>微信官方banner廣告</view> <view style=”min-height: 50px;”> <!– uni-app尚未封裝,但可直接使用微信原生的ad組件–> <ad unit-id=”adunit-01b7axxxbf53d74e”></ad> </view> <view class=”title”>微信官方視頻廣告</view> <view style=”min-height: 50px;”> <!– uni-app尚未封裝,但可直接使用微信原生的ad組件–> <ad unit-id=”adunit-9f340xxx64533″ ad-type=”video” ad-theme=”white”></ad> </view></view>
小程序端運(yùn)行效果如下:
包括微信小程序自定義組件、WXS、云開發(fā)這些復(fù)雜用法,在uni-app里一樣全面支持。
所以,結(jié)論是:使用uni-app框架開發(fā),在功能上和原生小程序開發(fā)沒有區(qū)別,不會(huì)有任何限制。
2. 性能體驗(yàn)
開發(fā)者常問的第二個(gè)問題:三方框架,內(nèi)部大多做了層層封裝,這些封裝是否會(huì)增加運(yùn)行負(fù)載,導(dǎo)致性能下降?
同樣是多慮了,uni-app不會(huì)導(dǎo)致性能下載,甚至對(duì)很多環(huán)節(jié)做了自動(dòng)優(yōu)化,很多場(chǎng)景下性能體驗(yàn)比微信原生開發(fā)更好。
類似使用vue.js開發(fā)web,不但不會(huì)造成性能比原生js差,反而由于虛擬dom和差量更新技術(shù)的運(yùn)用,在大多數(shù)場(chǎng)景下,比開發(fā)者手動(dòng)寫代碼操作dom的性能還好。
小程序中需要頻繁的寫setData代碼來更新數(shù)據(jù),這里很重要的就是差量數(shù)據(jù)更新。如果不做差量,代碼性能不好,如果每處邏輯都判斷差量數(shù)據(jù)更新,那代碼寫起來太麻煩了。
使用uni-app,底層自動(dòng)差量數(shù)據(jù)更新,簡(jiǎn)單而高性能。
我們從優(yōu)化理論、實(shí)測(cè)數(shù)據(jù)兩個(gè)維度來仔細(xì)說明。
2.1 理論:框架優(yōu)化方案
為提高性能體驗(yàn),小程序從架構(gòu)設(shè)計(jì)層面做了很多工作:
- 邏輯層、視圖層分離,避免JS運(yùn)算阻塞視圖渲染
- 單獨(dú)定義組件標(biāo)簽(wxml),減少DOM復(fù)雜度
- 精簡(jiǎn)樣式(wxss),提升渲染性能
- 復(fù)雜組件原生化(video/map等),解決web組件的功能/體驗(yàn)缺失
通過這些規(guī)范約束,大幅提升了小程序的整體性能體驗(yàn),但依然存在不少性能坑點(diǎn),其中以setData最為頻繁普遍。
這里引用微信官方的描述,簡(jiǎn)單介紹一下setData背后的工作原理:
小程序的視圖層目前使用 WebView 作為渲染載體,而邏輯層是由獨(dú)立的 JavascriptCore 作為運(yùn)行環(huán)境。在架構(gòu)上,WebView 和 JavascriptCore 都是獨(dú)立的模塊,并不具備數(shù)據(jù)直接共享的通道。當(dāng)前,視圖層和邏輯層的數(shù)據(jù)傳輸,實(shí)際上通過兩邊提供的 evaluateJavascript 所實(shí)現(xiàn)。
為簡(jiǎn)化開發(fā),微信將evaluateJavascript調(diào)用封裝成了setData JS方法,實(shí)現(xiàn)視圖層和邏輯層的數(shù)據(jù)傳輸,數(shù)據(jù)流示意圖如下:
setData的執(zhí)行會(huì)受到很多因素的影響,setData每次傳遞數(shù)據(jù)量過大或頻繁被調(diào)用(見微信官方介紹),都可能引發(fā)性能體驗(yàn)問題。
幸運(yùn)的是,uni-app在這兩個(gè)方面都有優(yōu)化。
2.1.1 減少 setData 傳遞數(shù)據(jù)量
假設(shè)當(dāng)前頁(yè)面有一個(gè)列表(初始值為a,b,c,d),現(xiàn)在要向列表后追加4個(gè)新列表項(xiàng)(e,f,g,h),我們分別以微信原生、uni-app 兩種模式編寫代碼。
小程序原生代碼:
page({ data:{ list:[‘a’,’b’,’c’,’d’] }, change:function(){ let newData = [‘e’,’f’,’g’,’h’]; this.data.list.push(…newData); this.setData({ list:this.data.list }) }})
如上微信原生代碼,change方法執(zhí)行時(shí),會(huì)將list中的a,b,c,d,e,f,g,h8個(gè)列表項(xiàng)通過setData全部傳輸過去。
uni-app 代碼:
export default{ data(){ return { list:[‘a’,’b’,’c’,’d’] } }, methods:{ change:function(){ let newData = [‘e’,’f’,’g’,’h’]; this.list.push(…newData) } }}
如上uni-app代碼,change方法執(zhí)行時(shí),僅會(huì)將list中的e,f,g,h4個(gè)新增列表項(xiàng)傳輸過去,實(shí)現(xiàn)了setData傳輸量的極簡(jiǎn)化。
uni-app借鑒了 westore JSON Diff庫(kù),在調(diào)用setData之前,會(huì)先比對(duì)歷史數(shù)據(jù),精確、高效計(jì)算出有變化的差量數(shù)據(jù),然后再調(diào)用setData,僅傳輸變化的數(shù)據(jù),這樣就實(shí)現(xiàn) setData 傳遞數(shù)據(jù)量的最小化,大幅提高通訊性能。
Tips:也許有些同學(xué)對(duì)傳遞數(shù)據(jù)從a,b,c,d,e,f,g,h8個(gè)列表項(xiàng)優(yōu)化為e,f,g,h4個(gè)列表項(xiàng),不以為然,但我們提醒,不要小看這個(gè)機(jī)制,上述只是demo示例。
- 在實(shí)際列表場(chǎng)景中,每個(gè)列表項(xiàng)可能包含縮略圖、標(biāo)題、摘要、時(shí)間等各種信息,每個(gè)列表項(xiàng)數(shù)據(jù)都會(huì)更大(假設(shè)為1k);
- 假設(shè)當(dāng)前頁(yè)面有20個(gè)列表項(xiàng),連續(xù)上拉4次后,頁(yè)面變成100條記錄;如果再次上拉,頁(yè)面變成120條記錄時(shí),情況會(huì)有不同
- 上述微信原生的方式,將120條記錄數(shù)據(jù)(120k)全部傳輸過去
- 上述 uni-app 模式,僅會(huì)將新增的20條(101 ~ 120)記錄數(shù)據(jù)(20k)傳輸過去,數(shù)據(jù)量是原生方式的1/6!
- 當(dāng)頁(yè)面列表項(xiàng)數(shù)據(jù)越多,這個(gè)差別就越大,頁(yè)面有200條記錄時(shí),uni-app傳遞數(shù)據(jù)量會(huì)變成微信原生數(shù)據(jù)傳遞量的1/10!
2.1.2 減少 setData 調(diào)用頻次
假設(shè)我們有更改多個(gè)變量值的需求,我們分別以微信原生、uni-app 兩種模式編寫代碼。
小程序原生代碼:
change:function(){ this.setData({a:1}); this.setData({b:2}); this.setData({c:3}); this.setData({d:4});}
如上四次調(diào)用setData,就會(huì)引發(fā)4次邏輯層、視圖層數(shù)據(jù)通訊
uni-app 代碼:
change:function(){ this.a = 1; this.b = 2; this.c = 3; this.d = 4;}
如上uni-app的代碼,最后會(huì)被合并成{“a”:1,”b”:2,”c”:3,”d”:4}一條數(shù)據(jù),然后僅調(diào)用一次setData完成所有數(shù)據(jù)傳遞,大幅降低了setData的調(diào)用頻次。
uni-app之所以有這樣的優(yōu)勢(shì),是因?yàn)?uni-app 基于 Vue Runtime 深度定制實(shí)現(xiàn),并借助了 Vue 的 nextTick 機(jī)制。
2.2 實(shí)測(cè):性能對(duì)比數(shù)據(jù)
有了如上的理論分析,我們接著進(jìn)行真機(jī)實(shí)測(cè),用數(shù)據(jù)來對(duì)比。
測(cè)試模型如下:
- 開發(fā)內(nèi)容:開發(fā)一個(gè)仿微博小程序首頁(yè)的復(fù)雜長(zhǎng)列表,支持下拉刷新、上拉翻頁(yè)、點(diǎn)贊。
仿微博的列表是一個(gè)包含很多組件的列表,這種復(fù)雜列表對(duì)性能的壓力更大,很適合做性能測(cè)試。
- 界面如下:
- 開發(fā)版本:使用微信原生、uni-app分別開發(fā)兩套代碼,uni-app使用cli方式默認(rèn)安裝。
- 測(cè)試代碼開源(Github倉(cāng)庫(kù)地址:https://github.com/dcloudio/test-framework), Tips:若有同學(xué)覺得測(cè)試代碼寫法欠妥,歡迎提交 PR 或 Issus,本項(xiàng)目下還有其它框架的測(cè)試代碼,開發(fā)者可忽略
- 測(cè)試機(jī)型:紅米 Redmi 6 Pro、MIUI 10.2.2.0 穩(wěn)定版(最新版)、微信版本 7.0.3(最新版)
- 測(cè)試環(huán)境:每個(gè)框架開始測(cè)試前,殺掉各App進(jìn)程、清空內(nèi)存,保證測(cè)試機(jī)環(huán)境基本一致;每次從本地讀取靜態(tài)數(shù)據(jù),屏蔽網(wǎng)絡(luò)差異。
從觸發(fā)上拉加載到數(shù)據(jù)更新、頁(yè)面渲染完成,需要準(zhǔn)確計(jì)時(shí)。人眼視覺計(jì)時(shí)肯定不行,我們采用程序埋點(diǎn)的方式,制定了如下計(jì)時(shí)時(shí)機(jī):
- 計(jì)時(shí)開始時(shí)機(jī):交互事件觸發(fā),框架賦值之前,如:上拉加載(onReachBottom)函數(shù)開頭
- 計(jì)時(shí)結(jié)束時(shí)機(jī):頁(yè)面渲染完畢(微信setData回調(diào)函數(shù)開頭)
Tips:setData回調(diào)函數(shù)開頭可認(rèn)為是頁(yè)面渲染完成的時(shí)間,是因?yàn)槲⑿舠etData定義如下(微信規(guī)范):
測(cè)試方式:從頁(yè)面空列表開始,通過程序自動(dòng)觸發(fā)上拉加載,每次新增20條列表,記錄單次耗時(shí);固定間隔連續(xù)觸發(fā) N 次上拉加載,使得頁(yè)面達(dá)到 20*N 條列表,計(jì)算這 N 次觸發(fā)上拉到渲染完成的平均耗時(shí)。
測(cè)試結(jié)果如下:
說明:以400條微博列表為例,從頁(yè)面空列表開始,每隔1秒觸發(fā)一次上拉加載(新增20條微博),記錄單次耗時(shí),觸發(fā)20次后停止(頁(yè)面達(dá)到400條微博),計(jì)算這20次的平均耗時(shí),結(jié)果微信原生在這20次 觸發(fā)上拉 -> 渲染完成 的平均耗時(shí)為876毫秒,uni-app是741毫秒。
這個(gè)數(shù)據(jù),可能違反了很多人的直覺,uni-app 的性能竟然比微信原生還好!
當(dāng)然,使用微信原生開發(fā),也可以自己?jiǎn)为?dú)寫代碼優(yōu)化setData。但每處業(yè)務(wù)都編寫太多判斷是不現(xiàn)實(shí)的,自然是用框架更舒心。
這個(gè)結(jié)果,和web開發(fā)類似,web開發(fā)也有原生js開發(fā)、vue、react框架等情況。如果不做特殊優(yōu)化,原生js寫的網(wǎng)頁(yè),性能經(jīng)常還不如vue、react框架的性能。
也恰恰是因?yàn)閂ue、react框架的優(yōu)秀,性能好,開發(fā)體驗(yàn)好,所以原生js開發(fā)已經(jīng)逐漸減少使用了。
3.社區(qū)生態(tài)
3.1 周邊輪子
小程序是脫離web自造生態(tài),很多web生態(tài)中輪子無法使用。
微信小程序還是有周邊生態(tài)的,而其他幾家小程序平臺(tái)的生態(tài)基本沒建起來。
uni-app的周邊生態(tài)非常豐富,在插件市場(chǎng)有近800個(gè)插件,詳見 ext.dcloud.net.cn。
首先uni-app兼容小程序的生態(tài),各種自定義組件均可直接引入使用。在此基礎(chǔ)上,uni-app的插件市場(chǎng),有更多vue組件,同時(shí)可跨多端使用,并且性能優(yōu)秀。
這使得uni-app的生態(tài)成為最豐富的小程序開發(fā)生態(tài)。
比如富文本解析、圖表等組件,uni-app的插件性能均超過了wxparse、wx-echart等微信小程序組件。
如果開發(fā)者需要豐富和高性能的組件,更應(yīng)該使用uni-app,而不是原生小程序開發(fā)。
3.2 活躍的QQ/微信群和論壇
uni-app官方有 70 個(gè)開發(fā)者QQ/微信交流群(大多2千人群,近10萬開發(fā)者),三方群更多。
問答社區(qū),每天有數(shù)百篇帖子?;钴S度與微信小程序官方論壇相同,遠(yuǎn)超過其他小程序官方論壇。
uni-app三方培訓(xùn)活躍,騰訊課堂官方都為uni-app制作了課程,各種培訓(xùn)網(wǎng)站到處可見免費(fèi)或收費(fèi)的uni-app培訓(xùn)視頻教程。
4.學(xué)習(xí)門檻、開發(fā)體驗(yàn)
首先微信原生的開發(fā)語(yǔ)法,既像React ,又像Vue,有點(diǎn)不倫不類,對(duì)于開發(fā)者來說,等于又要學(xué)習(xí)一套新的語(yǔ)法,大幅提升了學(xué)習(xí)成本,這一直被大家所詬病。
uni-app則對(duì)開發(fā)者更為友好,簡(jiǎn)單來說是 vue的語(yǔ)法 小程序的api。
它遵循Vue.js語(yǔ)法規(guī)范,組件和API遵循微信小程序命名,這些都屬于通用技術(shù)棧,學(xué)習(xí)它們是前端必備技能,uni-app沒有太多額外學(xué)習(xí)成本。
有一定 Vue.js 和微信小程序開發(fā)經(jīng)驗(yàn)的開發(fā)者可快速上手 uni-app 。
沒學(xué)過vue的同學(xué),也不用掌握vue的全部,只需了解vue基礎(chǔ)語(yǔ)法、數(shù)據(jù)綁定、列表渲染、組件等,其他如路由、loader、cli、node.js、webpack并不需要學(xué)。
因?yàn)镠BuilderX工具搭配uni-app可以免終端開發(fā),可視化創(chuàng)建項(xiàng)目、可視化安裝組件和擴(kuò)展編譯器,也就是uni-app的學(xué)習(xí)門檻,比web開發(fā)的vue.js還低。
開發(fā)體驗(yàn)層面,微信原生開發(fā)相比uni-app有較大差距,主要體現(xiàn)在:
- 更為強(qiáng)大的組件化開發(fā)能力:vue的組件開發(fā)比小程序自定義組件開發(fā)的體驗(yàn)要好很多
- 應(yīng)用狀態(tài)管理:uni-app支持vuex
- 使用 Sass 等 CSS 預(yù)處理器
- 完整的 ES Next 語(yǔ)法支持
- 自定義構(gòu)建策略
開發(fā)工具維度,差距更大:
- 微信開發(fā)者工具被吐槽無數(shù)
- uni-app的出品公司,同時(shí)也是HBuilder的出品公司,DCloud.io。HBuilder/HBuilderX系列是四大主流前端開發(fā)工具(可對(duì)比百度指數(shù)),其為uni-app做了很多優(yōu)化,故uni-app的開發(fā)效率、易用性非微信原生開發(fā)可及。
這里可以輸出一個(gè)結(jié)論:如果你需要工程化能力,那就直接忘了微信原生開發(fā)吧。
5.未來擴(kuò)展性
雖然當(dāng)前產(chǎn)品僅要求發(fā)布到微信小程序,但若有一天,老板和外來的一個(gè)和尚喝完咖啡,轉(zhuǎn)身就要求覆蓋阿里、百度、字節(jié)跳動(dòng)等各家小程序平臺(tái),此時(shí)程序員該怎么辦?
難道真的每個(gè)平臺(tái)到處搬磚嗎?
此時(shí),uni-ap的跨端功能將成為程序員的自救神器,基于uni-app開發(fā)的小程序,無需修改,即可同時(shí)發(fā)布到多家小程序,甚至App、H5平臺(tái)。這不是夢(mèng)想,而是現(xiàn)實(shí)。大家可依次掃描如下8個(gè)二維碼,親自體驗(yàn)最全面的跨平臺(tái)效果!。
6.結(jié)語(yǔ)
結(jié)論:只開發(fā)微信小程序,也應(yīng)該使用uni-app