阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

jopen 8年前發布 | 33K 次閱讀 HTML

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

去年(2015)四月份, 在 QCon 北京大會上分享了 阿里旅行 Hybrid 實戰經驗 ,作為航旅在 Hybrid 方向探索的一個收尾。當下集團內的重量級 App(手淘、錢包等)在 H5 容器建設上成長迅速,形成了宏大的技術體系,到去年雙十一,H5 容器所承載的流量已經遠遠超過了有限的 Native Page。就航旅來說,H5 承載的流量是 App 的至少四倍。無疑,處在應用層的 Web 技術棧,以其獨有的運行時環境(WebKit)、普適的技術標準(W3C & ES 5、6)以及極具優勢的研發靈活性,成為面向 UI 和交互無線研發的不二解決方案。而 H5 離線技術體系的逐漸成熟,讓 H5 和 Native 的融合達到前所未有的深度。

資源離線的思路簡單、場景復雜,最復雜的就是 H5 活動頁面的離線化。今天跟大家分享的就是航旅去年在 H5 活動頁推包體系 建設的一些實踐。

就加載性能來說,資源離線和發版頻度是一對矛盾。活動頁結構簡單,不具備復雜的業務邏輯,但變更極其頻繁,對時效性要求很高,這種更新頻繁程度在雙十一期間表現最甚。我們在去年 4 月份立項的 獨角獸項目 ,集中精力建設 活動頁推包體系 ,試圖克服這一對矛盾。

資源離線是加載性能優化的“二向箔”

Mobile Web 在弱網提速的唯一的辦法就是堅決杜絕不必要的(運行時)網絡請求 ,即除了 Json 格式的動態數據和其攜帶的商品配圖之外,不應再有其他網絡請求(埋點請求除外)。所以,HTML 和業務數據之間必須解耦。在此基礎上,航旅的 信鴿平臺 力爭完成這四項任務:

  1. 定時程序:緊隨頁面結構(HTML)變更進行推包
  2. 增量包:增量包(保性能)和全量包(保安全)必須同時提供
  3. 服務器推:基于長連接的消息推送 & 客戶端靜默更新
  4. 自動化:推包過程必須自動化,解放人工,搭好頁面點擊“發布”即完成推包

航旅的頁面也會通過 Zcache 在手淘中做離線,但由于缺少對線上頁面變更的監控,所以雙十一 會場頁面 仍然無法在 Zcache 中緩存 HTML,只能緩存 JS、CSS 和 Img。我們知道,HTML 是否緩存對弱網加載速度影響很大,下圖是航旅 雙十一主會場頁面 在兩個端里 2G 網絡下的加載瀑布:

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

可以看到,手淘 App 里的渲染時機被 HTML 網絡請求推后了,而且有一個更新后的 CSS 文件請求,不適時宜的阻塞了渲染。

定時程序動態推包

所以,針對去啊 H5 容器,我們寫了兩個程序來彌補 Zcache 在緩存動態頁面方面的不足,

  1. o2o 在線資源抓取程序 :基于  phantomjs  解析資源
  2. grunt-inc-offline 增量包計算器 :基于  git-diff  的增量包運算

當然 離線包生成器 也是必不可少的,我們用 信鴿平臺 將它們這樣整合起來:

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

  1. o2o  定時程序監聽線上頁面變更,將其所攜帶的資源(HTML、CSS、JS 和部分圖片)抓取下來
  2. 增量包計算器 會計算好與之前若干版本之間的增量文件,配合 包生成器 將增量包逐一構建打包,同時生成好每個增量包的  Diff Json
  3. 調用  Clam  命令通過  Gitlab  將資源包部署至 CDN,以備手機端更新。
  4. Gitlab 倉庫  的更新會觸發一個 Hook 腳本,調用  tSync  服務器的接口,來通知資源變更
  5. tSync 服務器沙箱完成消息封裝,包括了第二步生成了的  Diff Json  文本
  6. tSync 長連接將消息指令下發給手機終端
  7. 手機終端拼好資源文件鏈接,從 CDN 將增量包更新下來,隨后執行  Diff Json 中的指令,完成包的更新。

其中,獲取增量包時,手機會將本地離線倉庫版本帶上,和遠端 tSync 消息中的更新包版本一起拼成資源包的 URL( 一個真實的增量包 URL ),格式形如:

http://g.alicdn.com/trip/h5-op2op/{$線上最新版本}/{$本地包版本}.zip

另外, Diff Json 也很干凈,包含了“新增”、“刪除”、“更改”,這樣可以讓客戶端來刪除舊文件,減少新包覆蓋后的冗余。平臺的易用性上, 信鴿平臺 的操作界面里很貼心的加上了“快速下線”功能,即一旦發現離線包更新到達率不夠,可以立即做離線包下線,端的虛擬域會自動切換到線上頁面。

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

可以看到,整個系統關鍵在兩個平臺的銜接,即 信鴿平臺 和  tSync Server 。兩者的分工很明確:

  1. 信鴿平臺面向在線的 URL 完成資源抓取、構建和部署。
  2. tSync Server 完成消息推送和動態更新。

只要思路捋順,整個推包的邏輯設計并不難,難的是這些模塊的實現是否可靠健壯,其中較為核心的模塊就是 o2o 定時抓取程序,o2o 定時程序是@弘樹 開發的獨立的命令行腳本,將資源離線的過程中,需要根據文件內容來決定文件路徑的哈希值,即只要文件內容不變,離線后的引用路徑就不變,這樣就比較容易由  git-diff 程序來計算增量文件,畢竟文件是否屬于“新增”應當看內容是否有變化,而不應該根據文件名(或者版本號)的不同來判斷。

由于 o2o 是基于 phantomjs 來抓資源,所以,以 o2o 為原型我們衍生出了  o2o-capture 項目,將線上頁面完全靜態化到本地,用來做  TMS 系統掛掉的容災備份方案 ,也是棒棒的。

有了完整的外圍設施,手機端就可以聚焦在文件 IO 的性能優化上了, 之前也介紹過 ,航旅 H5 容器用多層保障來加速 Local File 的文件讀寫,一方面避免不必要的 IO、另一方面將資源池管理和運行時的緩存管理隔離開,確保各自程序任務聚焦、高效,下圖是手機端的兩個重要進程:

  1. 資源預加載進程:在實際訪問頁面之前,將資源預加載到緩存池并更新  Cache Map
  2. 創建 WebView 進程:只聚焦本地資源讀寫,別的什么也不干

所以手機端 touch 到網絡的環節收斂到了兩處,第一,Package Update Controller,第二,WebView 本身必要的網絡請求:

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

最終,在定時程序的幫助下,我們可以放心的將 HTML 也離線到端,而不必擔心更新不及時的問題,配合高性能的 H5 容器,做到秒出就是自然而然的事情了。我們來看 2G 下去啊 App 和 手淘加載 航旅會場頁 的速度對比,顯然,去啊 App 的離線更干凈徹底,不管首次加載還是二次加載,速度都是很可觀的:

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

從全網的性能數據看 亦是如此,下圖是航旅雙十一預售階段的數據,10月28日主會場頁在去啊、錢包、手淘里各種網絡情況下的 DomReady 時間統計。在 2G 網絡下,支付寶和手淘基本都卡在 HTML 請求阻塞上。

三端在三個網絡下的 DomReady 時間對比(單位秒),結果是顯而易見的:

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

應當說明的是,這是在手淘和錢包沒有條件緩存活動頁 HTML 資源的情況下拉的數據,依照上面的思路,我們也寫了一個外圍工具 zcache pusher ,來半自動化推送動態更新的頁面,理論上手淘也是可以 做到 2G 離線加速的 。

此外, Zcache 較早前就有計劃 和新版 TMS 嘗試打通 ,讓離線操作自動化起來,期待能盡快看到進展,和我們一樣,Zcache 也會面臨這個問題:“ 發版頻度和離線包更新到達率 ”的問題。那么,影響包的到達率的因素都是什么呢?

發版頻度 vs 離線包更新到達率

信鴿的整個體系對性能的考驗不是來自架構設計,而來自硬件瓶頸,尤其是當定時程序檢測到線上頁面頻繁部署(比如雙十一期間,航旅會場頁面每天更新頻率峰值多達四十多次每天),頻繁推包會帶來兩個問題:

  1. 手機終端是否能及時更新到最新版的離線包
  2. 如果要保證更新足夠及時,頻繁靜默更新又會大量占用手機的流量

顯然,這兩點是相互矛盾的。 我們既希望用戶盡可能及時的更新到最新版的離線包,又不希望這種頻繁推送過多占用手機流量。這種情況下,增量包只能確保用戶及時更新的情況下,盡可能少的占用流量,而無法完全杜絕 。也就是說,不管是手淘、錢包還是航旅 App,目前離線包的推送策略仍然過于“全量”,稍顯粗暴,用戶“無條件”接受所有更新。即目前所有端都做不到對用戶行為的精準判斷,做不到用戶需要(訂閱)A,我就給他推包 A。所以, 信鴿平臺 和  tSync Server 都存在很大升級空間。

So,在這次雙十一執行過程中,在航旅 App 里,這一對矛盾究竟如何表現?下圖是10月28日會場頁面最新一次推包后的 客戶端更新比例 ,左圖是推包 1 小時后,右圖是推包 2 小時后。

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

天哪,看看今天執行了多少次推包!

可以看到,相比于過去傳統的線上頁面部署,離線包的部署時效性顯然慢一些,不夠100%所見即所得。這也是為了換取加載速度不得不做的犧牲。但基本上每次推包 3 個小時候可以完成 90% 以上的更新。受用戶所在網絡和打開時機等因素影響,散落在手機端里的離線包舊版本的碎片化依然非常嚴重。 不管用了多少優化手段,頻繁修改頁面、頻繁推包都會對頁面體驗帶來負面影響。

所以,對于時效性很強的頁面,比如凌晨零點的發布需要切會場的場景,需要頁面即時部署即時生效。若要走離線有兩個方案可以選擇:

  1. 提前(至少四個小時)推離線包,需要在頁面中寫好定時切換的邏輯
  2. 提前推消息指令,先將離線頁面從端刪除,在切換時同時執行線上部署和離線推包, 去啊客戶端支持虛擬域 , 在線離線頁面 URL 在容器中保持一致,在保證線上頁面可用的情況下,逐步擴大離線包在端的覆蓋率。

但不論哪個方案,我們都不可能像過那樣部署線上資源那樣輕松了。 如果需要更高的時效性 + 更快的加載速度,則必須適度減少瑣碎需求變更,降低推包次數。從這個角度看,決定性能的因素這里已經主要不在技術上、而在工程上了。

今年手淘(天貓)雙十一主會場頁面也遇到同樣的狀況,本來 Weapp 可以非常優雅的將 H5 Page 轉義成 Native Page,理論上是可大大提速的,但還是 為了滿足頁面動態性更新和個性化配置,不得不引入一些額外的網絡開銷,這些網絡開銷不合時宜的阻塞了布局的渲染,在弱網里的影響更大。 我們來看去啊 App 里首次進航旅主會場(H5)和手淘中首次進天貓主會場在移動 3G 下的加載速度:

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

可以看到,H5 頁面是逐級加載的,Native Page 是等待請求完成后瞬時渲染的。所以,不管是 H5 還是 Native,只要是應對這種頻繁修改部署變更的活動頁面,都會遇到加載上的瓶頸。 信鴿平臺 是解決這對矛盾的一個緩沖,但根本上還是要從控制頁面靈活性角度來求解。

但是,這種離散性未必都是壞事,它能適度緩解安裝包體積膨脹的壓力。

安裝包體積極限

大家相信嗎, 手淘和貓客的安裝包都過百兆了。這已經到了一款電商 App 包體積的極限 。在 上一篇文章中也提到 ,目前客戶端技術架構在面對新功能的井噴時顯得力不從心。H5 是一個方案,將資源和內容置于遠端,但又會極大稀釋客戶端的體驗。離線包技術就很合事宜的彌合這對矛盾。

但這顯然不夠,和錢包 App 的早期一樣,航旅 App 在構建安裝包時就會“預裝”一部分重要 H5 資源,但面臨高速迭代的產品需求,這個緩沖區是遠遠不夠用的。目前,錢包和手淘顯然已經將這個緩沖擠占完全擠占:

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

以去啊 App v6.0 為例 ,7 M 的 H5 離線包承載了將近 40% 的功能性頁面 和 100% 的活動頁面。所以只要你的 H5 頁面質量夠高,H5 離線包的體積消耗是非常劃算的。 這也是在航旅 BU 正在發生的事情,即便是在交互極其華麗的“去啊 App 6.0 行程”項目中,PM 還是不斷從前端團隊抽調同學參與一些關鍵頁面的研發,一方面大家已經不擔心 H5 體驗的瓶頸,另一方面,“前端同學搭界面真是快!!!”

所以, 高性能 H5 容器 配合 高效的離線包推送體系 ,再加上 高質量的 H5 代碼 (通過  Clam 工具來保證),做出全網絡“無縫秒出”的體驗是完全沒有問題的( 體驗視頻 ):

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

大家還可以感受下航旅這次雙十一的無線 狂歡城和跑步游戲在3G網絡中的表現 ,

經過上面這些折騰,最終就達成了我們希望的結果:

  1. 快速的頁面研發
  2. 靈活的部署、持續交付
  3. 無縫秒出
  4. 劃算的功能體積比
  5. 時效性強的活動頁也能做到高效離線化!

這就是航旅無線技術團隊正在做的事情。好像很爽的樣子,下面我們來說但是吧。

另一種混合

由于 WebView 對 App 進程來說是一個沙盒,所以 H5 頁面的內存分配和 CPU 分片都是 WebView 獨立完成,前端代碼因為普遍缺少細致的內存管理,所以內存泄露時有發生,以至于H5 容器一定程度會影響 Crash 率。比如手淘 Android 就會限制打開的 WebView 堆棧的個數來減少內存壓力。

ReactNative 是一個解法,就像我跟@小馬 開玩笑時講的,“前端同學用 React 搭了一個 App,就好像 Java 開發同學用 Bootstrap 搭了一個后臺界面一樣興奮”。 和 Bootstrap 一樣,ReactNative 是業余 Native 開發同學的腳手架,是無法做出面向 C 端的產品的,只能做一做“阿里內外”這種量級的應用。

還有一個方向就是重新設計動態的 Native 頁面布局,集團內代表性的就是 鳥巢 、  Dynative 和今年雙十一手淘在嘗試的基于 Web Component 在三個端同構渲染的 Weapp,盡管對于復雜列表還是偶有性能問題,但至少整個 UI 的渲染已經脫離了 WebView,內存更加可控。 我們也必須承認,在運行時性能上,不管是 H5 翻譯 Native 還是原生 Native,都要強過 H5 容器的,尤其是在超長復雜列表的渲染上 。相對于鳥巢和 Dynative 的全 UI 渲染,航旅也在規劃 H5 和 Native 的交叉渲染技術的嘗試,總體思想是借助 JSCore 和一個刪減版的 Webkit 內核來渲染翻譯好的 HTML 片段,頁面交由 Native 來拼裝:

阿里巴巴技術文章分享:極致的 Hybrid:航旅離線包再加速!

這個方向我們也是剛剛起步,希望能和兄弟 BU 們一同共建。

小結

航旅在 Hybrid 方向上做的事情,并非要證明航旅 H5 比其他端快,畢竟應用場景不同(比如手淘就 有選擇的忽略 3G 和 2G 網絡 )。但從航旅和集團各 BU 的混合開發實踐來看,其實大家都在朝著一個方向努力, Native 期望獲得 H5 快速開發和部署能力、H5 期望獲得更快的速度和更高的硬件調用權限 ,兩個思路:

  1. H5 容器技術(得益于  Clam  工具的保障,手淘、錢包、去啊 各自的容器,已經做到90%相互兼容):
    1. 優勢:獨立的 WebView,對前端開發友好,天然獲得多端兼容的特性
    2. 劣勢:外圍體系化建設難度大
    3. 需要克服:一,硬件調用能力,通過 橋協議 解決;二,秒出保證,通過“離線包體系” + “精心編程的 H5 頁面”解決
    </li>
  2. H5 代碼 Native 化( 鳥巢 、 Dynative 、ReactNative、Weapp,互不兼容):
    1. 優勢:H5 代碼編譯成二進制代碼直接運行,天然的秒出體驗
    2. 劣勢:對前端開發極其不友好
    3. 需要克服:一,閹割版的布局能力,通過增加對 CSS3 標簽的支持來解決;二,無法做到多端兼容,通過限制 H5 語法來解決
    4. </ol> </li> </ol>

      可見,兩個思路都各有取舍、各有克服,都很難完美,從實踐效果來看,H5 容器更加適合哪些對多端部署有要求的 BU,航旅就是一個典型。而 H5 的 Native 化方案更加適合獨立客戶端的一些私有場景,比如支付寶和天貓。所以要根據自身需求來選擇技術路線。

      我作為一名傳統的前端工程師,從 PC 時代轉戰到無線,從去年航旅開始無線研發模式的探索以來,我也很幸運的嘗鮮各種 Native 技術,從開始的好奇,到現在一大堆體系和工具的落地,一系列探索讓 我自己腦洞大開 ,也打破了之前固有的編程理念,這兩年前端技術被顛覆的如此劇烈,讓人有點 不敢相信自己的眼睛 。我想 一方面,PC Web 開發的迅速衰落為無線前端技術快速崛起帶來契機,另一方面,無線技術快速崛起,帶來的不僅僅是技術體系的混合(H5 和 Native),更多的呼喚人的混合 。我們很欣慰的看到一大堆前端同學在研究 ReactNative,另外一大堆 Native 同學在研究 W3C 和 HTML5。打破技術邊界、擁抱無線技術的 All In,充滿好奇,用懷疑一切的眼睛去看待自己固有的技術理念,投身并享受新一輪的無線技術變革,我想,或許正是因為此,使得阿里無線端技術體系伴隨業務的增長,不斷走向百花齊放、走向多元的吧。

      To Be Continue...

      一些 Q & A:

      Q:現在 Wifi 是最多的用戶網絡,為什么要糾結于弱網用戶?

      A: 首先,我們希望在最嚴苛的環境中考練技術,再者,廣大(地級)市、縣鄉這些 Wifi 覆蓋率低的地區,我們都親身體驗過那里 4G 和 3G 是什么網速。

      Q:這種強混合的研發模式,對前端技術框架有什么影響?

      A: 影響是顛覆式的。前端的模塊化編程過于依賴 Loader 和上層的模塊規范,而 Mobile Web 里是不是還強依賴 Loader 要打一個問號,一方面,Loader 本身太重,另一方面,Loader 是在運行時去組織資源依賴加載,顯然會搶占寶貴的運行時資源,資源的組織和加載應當下沉交給更底層的 H5 容器或者工具去解決。

      Q:H5 容器即是瀏覽器,怎么去平衡 Web 的加載性能和運行時性能?

      A: 這篇文章主要說的就是加載性能的解決方案。運行時性能我們也有一攬子的 最佳實踐 ,另開一篇介紹。

      Q:基于 H5 容器畢竟不像瀏覽器,怎么快速打離線包調試?

      A: 這方面手淘、錢包 都有最佳實踐。航旅通過工具可以實時構建 zip 離線包, 直接拷貝到手機即可 。目前是最土,也是最有效的辦法。

      Q:航旅怎么做到 7 M 的離線包完成 App 里40%的功能頁面?

      A: 我們化了一整年來做體積瘦身的優化,另開篇介紹吧。

      Q:上面提到的離線數據從哪里來的?

      A: 航旅自己提供了一個非常全面的打點方案  tracker ,目前部署上抽離的還不是很夠,但基本上我們想要的關鍵數據可以比較精確的取到了。大部分數據可以通過 魚眼 來查看。

      該文章來自阿里巴巴技術協會( ATA )精選集

      </div>

      來自: http://yq.aliyun.com/articles/2939?spm=5176.100239.yqblog1.10

       本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
       轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
       本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!