跨端徹底,直接發(fā)行,無需二次開發(fā);
通過Tree-Shaking搖出最小化內(nèi)置組件等優(yōu)化策略,提升性能
這應(yīng)該是uni-app在H5平臺(tái)的相對(duì)其他小程序框架更友好的地方
背景
隨著微信小程序的火爆及百度、頭條小程序的持續(xù)推進(jìn),跨端開發(fā)的需求愈發(fā)迫切,業(yè)界隨之出現(xiàn)了一系列的跨端框架,但對(duì)于H5平臺(tái)跨端支持的都不太徹底:
Vue技術(shù)棧的小程序框架:對(duì)于H5平臺(tái)支持普遍較弱
部分React技術(shù)棧的小程序框架:雖支持生成可在H5端運(yùn)行的代碼,但僅僅是代碼可運(yùn)行,離項(xiàng)目直接發(fā)行上線的目標(biāo)還存在一定差距。
鑒于客觀需求及現(xiàn)狀,DCloud前端團(tuán)隊(duì)響應(yīng)開發(fā)者徹底跨端的呼聲,經(jīng)過連續(xù)奮戰(zhàn),uni-app1.2版本支持發(fā)行到H5平臺(tái),完整模擬小程序生命周期、事件處理、組件規(guī)范等,真正實(shí)現(xiàn)“一套代碼、多端發(fā)行”的目標(biāo)。
https://uniapp.dcloud.io/h5/ (二維碼自動(dòng)識(shí)別)
本文主要分享,我們?cè)趯?shí)現(xiàn)uni-app發(fā)行到H5平臺(tái)時(shí),在引擎實(shí)現(xiàn)、差異抹平、性能優(yōu)化方面都做了哪些工作。
完整模擬小程序引擎
uni-app設(shè)計(jì)的開發(fā)標(biāo)準(zhǔn)是:Vue.js的語(yǔ)法 + 小程序的API + 條件編譯擴(kuò)展平臺(tái)個(gè)性化能力。其中:
Vue.js 的語(yǔ)法在微信小程序端,uni-app是在mpvue的基礎(chǔ)上增強(qiáng)實(shí)現(xiàn)的,在H5端則默認(rèn)支持;
而小程序的API,其實(shí)包括三個(gè)部分:框架 + 組件(UI)+ 接口(API),這三部分在微信小程序端是內(nèi)置支持的,而uni-app若要發(fā)布到H5平臺(tái),則需完整模擬實(shí)現(xiàn)小程序運(yùn)行時(shí)環(huán)境。
如下是一個(gè)簡(jiǎn)易的小程序運(yùn)行時(shí)框架,核心是一個(gè)響應(yīng)的數(shù)據(jù)綁定系統(tǒng)。
為實(shí)現(xiàn)小程序、H5兩端的完整跨端,uni-app在H5平臺(tái)完整模擬實(shí)現(xiàn)了小程序的邏輯層和視圖層,相比業(yè)界其它跨端框架,uni-app在H5平臺(tái)有如下幾點(diǎn)實(shí)現(xiàn)更完善。
頁(yè)面配置
小程序中的導(dǎo)航條、選項(xiàng)卡是通過配置文件生成的,配置后由原生組件進(jìn)行渲染,uni-app在H5平臺(tái)同樣兼容這些配置,不過會(huì)降級(jí)通過div控件模擬實(shí)現(xiàn),因此開發(fā)者無需單獨(dú)為H5平臺(tái)添加導(dǎo)航條或選項(xiàng)卡。
生命周期
uni-app在H5平臺(tái)實(shí)現(xiàn)了完整的小程序生命周期,為此填了很多坑。舉一個(gè)詳情頁(yè)互跳的栗子:
詳情A 打開 詳情B,在通常的 web 端 SPA 方案中,會(huì)在詳情A頁(yè)面獲取B詳情的數(shù)據(jù),僅會(huì)觸發(fā)詳情頁(yè)A的updated生命周期,不會(huì)觸發(fā)onHide;但在小程序中,則會(huì)打開一個(gè)新的webview并加載詳情B,此時(shí)會(huì)觸發(fā)詳情A的onHide生命周期,也會(huì)觸發(fā)詳情B的onShow生命周期;uni-app完整模擬了小程序的生命周期,詳情頁(yè)之間互相切換時(shí),會(huì)觸發(fā)onHide、onShow等生命周期;這樣的實(shí)現(xiàn),即保證了兩端兼容性,同時(shí)在詳情B返回詳情A時(shí),詳情A已被緩存,無需再次聯(lián)網(wǎng)加載,也會(huì)有更高的性能。
事件處理
uni-app對(duì)于頁(yè)面事件處理函數(shù)支持更為全面,下拉刷新、上拉觸底等常用函數(shù)均可在H5平臺(tái)正常復(fù)用,無需二次開發(fā)。
組件規(guī)范
uni-appH5平臺(tái)的組件實(shí)現(xiàn),有兩個(gè)特點(diǎn):
兼容的組件數(shù)量更多:比如navigator等組件在H5平臺(tái)可正常跳轉(zhuǎn)
組件屬性、嵌套實(shí)現(xiàn)更接近小程序?qū)崿F(xiàn)
抹平引擎差異
fixed元素遮擋
微信小程序是一種 native + web 混合渲染的機(jī)制,比如小程序的導(dǎo)航條(navigationBar)、選項(xiàng)卡(tabBar)為原生組件,但H5平臺(tái)為純 web 渲染,導(dǎo)航條、選項(xiàng)卡均為 web 實(shí)現(xiàn),這可能引發(fā)頁(yè)面 fixed 元素 和導(dǎo)航條/選項(xiàng)卡位置發(fā)生互相遮擋的問題,如下一段 fixed 定位的代碼:
.fixed{
position: fixed;
z-index: 9999;
bottom: 0px;//底部距離為0
background-color:peru;
}
在不同平臺(tái)上運(yùn)行效果不同,如下圖所示:
uni-app通過引入css變量解決這類問題,在編譯到不同平臺(tái)時(shí),給css變量設(shè)置對(duì)應(yīng)的值。
有了css變量,開發(fā)者若需處理 fixed 定位的元素,只需像如下方式編寫即可:
.fixed{
bottom:var(--window-bottom)
}
css作用域
uni-app在開發(fā)時(shí)遵循 Vue 單文件組件 (SFC) 規(guī)范,編譯到微信小程序時(shí)會(huì)生成對(duì)應(yīng)的 wxml 文件,最終運(yùn)行時(shí)由 webview 渲染,iOS 平臺(tái)由 WKWebView 渲染,Android 平臺(tái)由 XWeb 引擎基于 Mobile Chrome 53 內(nèi)核渲染;uni-app中的不同.vue頁(yè)面文件( 編譯后的.wxml 文件),在小程序端會(huì)由不同的 webview 渲染,故 .vue頁(yè)面文件中的 css 作用域是天然隔離的,開發(fā)者無需在<style> 標(biāo)簽上增加scoped 屬性。但H5平臺(tái)是一套SPA框架,無scoped就會(huì)變成全局樣式,影響其他頁(yè)面。uni-app在H5平臺(tái)做了智能處理,自動(dòng)增加了scoped。
平臺(tái)性能優(yōu)化
性能一直是 web app 首要關(guān)注的焦點(diǎn),uni-app發(fā)行到H5平臺(tái)時(shí)也做了很多性能優(yōu)化。
內(nèi)置組件按需打包(Tree-Shaking)
uni-app有8大類、幾十個(gè)內(nèi)置組件,但開發(fā)者實(shí)際開發(fā)時(shí)僅會(huì)使用其中的一部分組件,比如很多App不會(huì)用到map、canvas等組件,若打包時(shí)將uni-app整個(gè)組件類庫(kù)都打包進(jìn)去,則會(huì)造成極大的資源浪費(fèi),延遲首頁(yè)渲染速度。
uni-app發(fā)行到H5平臺(tái)時(shí)采用了搖樹優(yōu)化(Tree-Shaking)策略,將開發(fā)者項(xiàng)目中沒用到的組件從整個(gè)框架中“搖”掉,保證編譯后的 JS 文件最小化。具體來說,uni-app編譯到H5平臺(tái)時(shí)分為預(yù)編譯、再編譯兩個(gè)階段,預(yù)編譯階段通過vue-template-compiler分析出來的AST,映射生成項(xiàng)目中使用到的組件清單,然后再基于Webpack插件將使用到的組件編譯生成一個(gè)最小化的uni-app框架文件。
我們以u(píng)ni-app的兩個(gè)開源項(xiàng)目模板登錄模板、看圖模板為例,測(cè)試 Tree-Shaking 前后組件框架的大小,效果喜人,數(shù)據(jù)如下:
路由組件按需加載(Lazy-Loading)
當(dāng)打包構(gòu)建 SPA 應(yīng)用時(shí),Javascript 包會(huì)變得非常大,影響頁(yè)面加載。雖然開發(fā)者基于Vue 的異步組件和 Webpack 的code-splitting 功能,可以實(shí)現(xiàn)路由組件的懶加載,但開發(fā)者需調(diào)整.vue源碼及Webpack配置,有一定的學(xué)習(xí)門檻,且比較繁瑣。
uni-app在H5平臺(tái)實(shí)現(xiàn)了自動(dòng)按需加載路由組件,開發(fā)者無需調(diào)整組件開發(fā)方式,僅需關(guān)心業(yè)務(wù)實(shí)現(xiàn)即可。
其它方面
uni-app為提升性能體驗(yàn),在很多細(xì)節(jié)上都有特殊設(shè)計(jì)。比如常見的 SPA 框架一般采用div區(qū)域滾動(dòng),uni-app為改善用戶體驗(yàn),使用的是body滾動(dòng),由此填了很多坑,比如不同頁(yè)面的background-color,若使用div滾動(dòng),則在編譯階段就可完成樣式定義,但基于body滾動(dòng),就需要在頁(yè)面前進(jìn)、后退時(shí)動(dòng)態(tài)設(shè)置body的背景色。
github
uni-app在H5平臺(tái)的相關(guān)代碼均已全部開源,詳見uni-app,歡迎大家 star 支持.