- 跨端徹底,直接發行,無需二次開發;
- 通過Tree-Shaking搖出最小化內建元件等優化策略,提升效能
這應該是uni-app在H5平臺的相對其他小程式框架更友好的地方
背景
隨著微信小程式的火爆及百度、頭條小程式的持續推進,跨端開發的需求愈發迫切,業界隨之出現了一系列的跨端框架,但對於H5平臺跨端支援的都不太徹底:
Vue
技術棧的小程式框架:對於H5平臺支援普遍較弱- 部分
React
技術棧的小程式框架:雖支援生成可在H5端執行的程式碼,但僅僅是程式碼可執行,離專案直接發行上線的目標還存在一定差距。
鑑於客觀需求及現狀,DCloud前端團隊響應開發者徹底跨端的呼聲,經過連續奮戰,uni-app
1.2版本支援發行到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已被快取,無需再次聯網載入,也會有更高的效能。
方法 | 作用 |
---|---|
onLoad | 監聽頁面載入 |
onShow | 監聽頁面顯示 |
onReady | 監聽頁面初次渲染完成 |
onHide | 監聽頁面隱藏 |
onUnload | 監聽頁面解除安裝 |
事件處理
uni-app
對於頁面事件處理函式支援更為全面,下拉重新整理、上拉觸底等常用函式均可在H5平臺正常複用,無需二次開發。
方法 | 作用 |
---|---|
onPullDownRefresh | 頁面相關事件處理函式--監聽使用者下拉動作 |
onReachBottom | 頁面上拉觸底事件的處理函式 |
onPageScroll | 頁面滾動觸發事件的處理函式 |
onTabItemTap | 當前是 tab 頁時,點選 tab 時觸發 |
元件規範
uni-app
H5平臺的元件實現,有兩個特點:
- 相容的元件數量更多:比如
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變數 | 描述 | 小程式 | H5 |
---|---|---|---|
--window-top | 內容區域距離頂部的距離 | 0 | 若有導航條則為導航條 的高度,否則為0 |
--window-bottom | 內容區域距離底部的距離 | 0 | 若有TabBar則為TabBar 的高度,否則為0 |
有了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 前後元件框架的大小,效果喜人,資料如下:
專案 | 優化前 | Shaking優化後 |
---|---|---|
登入模板 | 148k | 64k |
看圖模板 | 148k | 53k |
路由元件按需載入(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 支援.