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