330
技術社區[雲棲]
極致的 Hybrid 混合式開發(去啊App Hybrid 實戰)
該文章來自於阿裏巴巴技術協會(ATA)精選文章。
IO 優化
今天 去啊 App 5.1.1 已經發布了,航旅 Hybrid 混合架構有了更進一步的落地,這輪優化目標是搞定H5真正的“無縫秒出”。
先來看效果,去啊App 2G 網絡下購買國際機票,30秒完成,除了搜索入口頁,列表往下到付款頁的前端都是H5 Page,大家感受一下:
目測性能是可觀的。盡管H5包的離線化隔絕了弱網對秒出的幹擾,設備本地 IO 耗時也是不能忽視的,算上zip的解壓縮,僅在設備本地 IO 完全一個 HTML(包含其攜帶的資源文件)也會達到秒級的耗時,在iphone5上也會有0.5秒左右的白屏時間。
另外,HTML 本身的優化依然無法繞過,WebView 裏 JS 的運行效率通常是 Mobile Browser 裏的四分之一。所以 JS 必須盡可能靠後的介入渲染,CSS 必須盡可能靠前的介入渲染。而在當下前端開發習慣來看,頁麵通常會至少阻塞加載一個種子文件(比如kissy),而在Mobile設備中,哪怕是無幹擾Dom的JS阻塞運行都會帶來0.3秒左右的白屏延時。
所以,H5容器的IO優化和HTML渲染提前是本期改造的重點,即:
- H5 容器加載資源的 IO 優化:幹掉zip包的即時解壓,離線包更新後立即解壓散列到SD卡,每次創建 View 時直接從設備讀文件,本地文件管理依然基於標準的H5包規範。
- HTML 本身的頁麵優化,CSS 提前,JS 置後。
“CSS 提前和JS置後”的動作是由工具來完成。即隻要構建工具統一,開發者不需要關心如何擺放腳本最優,隻需關注實現業務邏輯即可,舉個例子,JS 置後的做法是這樣:
其實無非是將同步的腳本改成異步。先保證帶樣式的頁麵框架秒出來,然後去執行 JS。從性能數據上甚至看不出差別,但從感官上的提升非常明顯,我寧願讓你先看到界麵,而不是白屏。
IO 優化(續)
從策略上,做到這兩點足夠應付大多數場景,能保證頁麵任何時候能秒出來。但在我們整個 Hybrid 架構中,我們設計了比較靈活的 H5 離線化,即用虛擬域來確保在線離線的一致,比如酒店團購H5頁麵,瀏覽器掃碼打開是一個在線頁麵,用去啊App掃碼進來就是一個離線頁麵,同一份代碼,一個走網絡加載,一個走本地加載:
這樣設計主要是為了做線上線下的開關切換,緊急問題可隨時配置到線上頁麵,線上頁麵是可以隨時部署的,離線頁麵則涉及到推包。為了做這層開關,就會帶來判斷文件是線上還是離線的問題。
因為H5容器虛擬域的代理層會引導 WebView 去本地而不是網絡讀文件。如果讀不到本地文件,再創建一個HTTP請求去對應的線上請求文件。如果通過 IO 一次再判斷本地是否存在文件,顯然實際的 IO 次數依然降不下來(所有的資源文件請求都必須要 IO 一次手機硬盤),為了降低實際 IO 次數,我們針對每個 H5 離線包生成一個本地資源文件列表(cache_info.json),並同時將域名路徑和文件路徑做成了映射 Map,這個映射表讀入內存後備用,涉及到H5的訪問,用這個 Map 過濾下就能直接找到要讀的文件位置,Map 匹配不上就直接創建HTTP從網上取文件了,這樣可以避免無必要的 IO。
AngularJS 在移動端的加速
去啊 Hybrid 中存在大量的列表頁,比如上麵的團購和視頻中國際機票的例子,AngularJS 是最適用於這種場景。但 AngularJS 目前沒有專門針對 Mobile 做優化,而在 Mobile 設備裏,hashchange
帶動數據模型data-model
的變更,進而通過View
來渲染。首次渲染稍慢,因為要等Model
準備好才出視圖,無論如何界麵也秒不出來(從hashchange
到出界麵至少0.8 秒)數據結構在稍微複雜點,立即破1秒,當然這個時間是伴隨著首次加載構建DOM的幹擾。
幾點改造:
- AngularJS 種子文件異步載入
- 非數據關聯的HTML一律預裝在頁麵
- 首次加載幹掉任何影響頁麵抖動的 HashChange
- 基礎數據的離線化(比如城市列表)
這幾點無非是讓首次渲染能盡快的展現,接下來 OPOA 中的編程就是 AngularJS 所擅長的了。
離線包裏的 TMS 如何載入
我們知道 AWP 隻支持靜態 HTML 的發布,這沒什麼好解釋的,畢竟,高性能要求更簡單粗暴且有效的緩存,全靜態就可以全緩存,尤其是在移動終端的破網裏麵,緩存尤其重要,但 TMS 動態內容如何生成?我們都知道 AWP 平台提供了一個<!--HTTP:url-->
的標簽(使用說明),TMS 變更後就重新生成一份HTML 推送到CDN上。
那麼問題來了,離線包裏怎麼做?
我們團隊的同學寫了offline-tms-parser模塊,clam會將<!--HTTP:url-->
標簽構建:
<!--HTTP:https://abc.php,gbk:HTTP-->
構建為:
<script
src="https://trip.taobao.com/market/trip/h5_offline_service.php?
callback=handle_tms_fragment&src=http%3A%2F%2Fabc.php"
charset="gbk"></script>
這樣,在離線包裏的 TMS 內容就和 H5 頁麵完全分開了,畢竟 TMS 由於變更頻繁,是沒辦法直接做離線化的。但上麵這段腳本顯然會阻塞頁麵渲染,所以offline-tms-parser
提供了異步的版本,即將:
<!--HTTP:https://abc.php?async,gbk:HTTP-->
構建為:
<script id="tms_fragment_1">
get_tms_fragment("https://abc.php", "gbk", "tms_fragment_1");
</script>
然後在 H5 頁麵頂部塞一個get_tms_fragment
的實現即可。
如此,基於 AWP 平台開發業務將不受任何影響,工具幫我們處理好 TMS 和 H5 頁麵的百分百解耦,離線包裏也可以大量使用 TMS 了。
盡管如此,也必須不能濫用 TMS,代碼邏輯層麵的 View 和 Data 的解耦仍然是必須要做的。
讓人期待的 grunt-kmb
本期優化麵向 H5 離線容器的代碼改造的重點是上麵這幾項,但還有一項激動人心的變化: grunt-kmb,沒錯,構建流程也需要瘦身和簡化了。
grunt-kmb
是團隊另一位同學正在開發的 grunt-kmc 的替代方案。相比於 grunt-kmc 基於正則匹配的模塊解析,grunt-kmc 完全基於 uglify-js
提供的 JavaScript 語法解析樹(AST),先看對比:
grunt-kmc 的速度:
grunt-kmb 的速度:
整整一倍的提速,太讓人垂涎期待了。
What's Next
本期的優化沒有多少高科技的東西,大都是體力活,將技術做透。好的體驗真的是靠點滴的積累,需要花時間去磨。
其實從去啊App Hybrid 剛開始設計並做第一版優化到現在已經有半年多時間,這期間離不開客戶端同學的全心投入,因為 H5 的優化必須借助高性能的 WebView 容器,但靠 H5 或者 Web 技術本身無論如何是無法做到秒出的。再配上《高性能網站建設指南》裏零碎的優化技巧,H5 在 Hybrid 中完全可以做到秒出,再配備離線包動態推送和埋點采集等基礎設施,Web 技術的瓶頸在 Mobile 中就能獲得一定的突破。
我在這次集團前端技術峰會上的匯報裏,提到過我們麵臨的挑戰:
去啊 App 是介於工具化的錢包App和運營化的手淘App之間,既有營銷活動,也有工具化、流程化的 PageFlow。將標準化的 PageFlow 的性能做到極致,接下來的挑戰就是如何將運營活動也做到智能的推送,完成這類頁麵的離線部署。
當然,活動頁麵的離線化部署目前來看不是我們麵臨最急迫的難題,最棘手的是數據打通的問題:
看這個場景,在錢包App做了一個引流的入口,喚起了去啊App,並定位到機票搜索結果頁:
目前我們很難跟蹤喚起的效果,手機裏的App是信息孤島,很難通過簡單的傳參來把跨 App 的 PageFlow 串聯起來。即使參數能帶過來,但身份信息、登陸狀態和賬號關聯能否也能帶過來呢,每一項都是很有挑戰。
我在前兩天給航旅的新人培訓上,分享了我理解的《Mobile First》,這段話是值得分享給大家一起共勉的:
內聚的 App 和散列的 Web 似乎是一個不可調和的矛盾。企業傾向於認為隻有提供越來越多地功能,才能滿足用戶不斷膨脹的需求,但又會打破原有應用的簡便易用。當兩者無法調和,信息膨脹到必須散列到不同的端時,通過 Web 技術將這些信息孤島關聯起來就顯得至關重要。
所以,我們之前所做的所有技術的優化,都是在為構建無線“前端/終端”技術體係夯實根基,所以這一輪無線All In 從某種意義上看是一種原始積累,第二輪無線All In才會迎來真正的非標商品的個性化、多元化時代。這時我們的技術體係將著重解決這幾類問題:
- 千人千麵,重點解決麵向不同人群做手機裏的定製化功能的問題
- 無線大數據,重點解決打破App間的信息孤島,讓跨端的數據化運營更加高效、可靠
- 無線開源,讓 B 商家參與進來,像手淘一個(Native)商品詳情頁通吃所有商品的時代很快就會被更個性、多彩的非標商品打破,這時,大量垂直領域的產品模式設計更多要靠商家參與,而不是我們自己那幾個產品經理,所以,更開源、更自由的手機店鋪,閉環服務才是王道。
說到閉環,去啊的機票購買流程,是無線端閉環的經典案例:
這個例子是從錢包的入口開始購機票流程,通過短信、Push、下載、喚起等操作,將用戶搗騰到去啊App裏(整個過程體驗流暢,估計你也很難分清楚哪些Page是H5的、哪些是Native的吧)。
So,開源 + 閉環,是我理想中的無線 Hybrid 技術的終極狀態,去啊 Hybrid 技術積累也才剛剛開始。
最後更新:2017-04-01 13:37:10