閱讀330 返回首頁    go 技術社區[雲棲]


極致的 Hybrid 混合式開發(去啊App Hybrid 實戰)

該文章來自於阿裏巴巴技術協會(ATA)精選文章。

IO 優化

今天 去啊 App 5.1.1 已經發布了,航旅 Hybrid 混合架構有了更進一步的落地,這輪優化目標是搞定H5真正的“無縫秒出”。

先來看效果,去啊App 2G 網絡下購買國際機票,30秒完成,除了搜索入口頁,列表往下到付款頁的前端都是H5 Page,大家感受一下:

be4c2c9b4fa8d3e0d2e7ec92df37403a.gif

目測性能是可觀的。盡管H5包的離線化隔絕了弱網對秒出的幹擾,設備本地 IO 耗時也是不能忽視的,算上zip的解壓縮,僅在設備本地 IO 完全一個 HTML(包含其攜帶的資源文件)也會達到秒級的耗時,在iphone5上也會有0.5秒左右的白屏時間。

另外,HTML 本身的優化依然無法繞過,WebView 裏 JS 的運行效率通常是 Mobile Browser 裏的四分之一。所以 JS 必須盡可能靠後的介入渲染,CSS 必須盡可能靠前的介入渲染。而在當下前端開發習慣來看,頁麵通常會至少阻塞加載一個種子文件(比如kissy),而在Mobile設備中,哪怕是無幹擾Dom的JS阻塞運行都會帶來0.3秒左右的白屏延時。

所以,H5容器的IO優化和HTML渲染提前是本期改造的重點,即:

  1. H5 容器加載資源的 IO 優化:幹掉zip包的即時解壓,離線包更新後立即解壓散列到SD卡,每次創建 View 時直接從設備讀文件,本地文件管理依然基於標準的H5包規範。
  2. 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的幹擾。

幾點改造:

  1. AngularJS 種子文件異步載入
  2. 非數據關聯的HTML一律預裝在頁麵
  3. 首次加載幹掉任何影響頁麵抖動的 HashChange
  4. 基礎數據的離線化(比如城市列表)

這幾點無非是讓首次渲染能盡快的展現,接下來 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才會迎來真正的非標商品的個性化、多元化時代。這時我們的技術體係將著重解決這幾類問題:

  1. 千人千麵,重點解決麵向不同人群做手機裏的定製化功能的問題
  2. 無線大數據,重點解決打破App間的信息孤島,讓跨端的數據化運營更加高效、可靠
  3. 無線開源,讓 B 商家參與進來,像手淘一個(Native)商品詳情頁通吃所有商品的時代很快就會被更個性、多彩的非標商品打破,這時,大量垂直領域的產品模式設計更多要靠商家參與,而不是我們自己那幾個產品經理,所以,更開源、更自由的手機店鋪,閉環服務才是王道。

說到閉環,去啊的機票購買流程,是無線端閉環的經典案例:

這個例子是從錢包的入口開始購機票流程,通過短信、Push、下載、喚起等操作,將用戶搗騰到去啊App裏(整個過程體驗流暢,估計你也很難分清楚哪些Page是H5的、哪些是Native的吧)。

So,開源 + 閉環,是我理想中的無線 Hybrid 技術的終極狀態,去啊 Hybrid 技術積累也才剛剛開始。

最後更新:2017-04-01 13:37:10

  上一篇:go 平台化三部曲之一微核心可擴展架構 - 從Eclipse平台看交易平台化
  下一篇:go 麵向GC的Java編程