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