無線webapp安裝更新機制

摘要 php

爲了知足移動終端:節省流量、減小請求、提升客戶端性能的需求,咱們設計了webapp安裝更新程序,把js、css、html和圖片這些資源,序列化爲字符串存入客戶端本地存儲,並帶上版本號來實現資源細粒度更新。css

TAGhtml

webapp 安裝啓動 性能優化前端

一、概述

咱們認爲webapp是一站式的應用,在一個頁面裏能完成整站的功能。因此,之前經過頁面全刷的跳轉,如今變成了經過底層框架來支持的局刷和切換動畫。爲了支持這些功能,會多出很多的代碼,再加上app裏的功能代碼,咱們統稱爲資源,包括底層庫js(zepto、iscroll、baiduTemplate等),通用ui組件和app功能性的js、css、html和圖片。web

如何處理一個頁面裏的這麼多資源,才能下降對性能的影響呢?爲此,咱們設計了webapp安裝更新程序,能夠作到減小資源請求,節省流量,提高客戶端性能。ajax

 

二、瀏覽器緩存方案

使用瀏覽器對資源緩存,這是一般的作法,能快速加載頁面,只需設置資源一個較長的過時時間便可,當服務器端資源有更新時,改變資源路徑就能使客戶端及時獲取更新。json

但缺點是,在webapp應用場景中,有大量的資源須要被下載,資源請求數可能過多,目前正在開發的貼吧webapp宙斯版,已經有60個請求了,預計會過百,固然咱們能夠把資源文件合併,但又帶來了另一個問題,下載粒度較大。當更新了一個較小部分,會致使大粒度資源被從新下載。因爲手機硬件和手機網絡的限制,每多一個鏈接請求的時間消耗和資源下載致使的流量耗費,都是無線webapp要考慮的重要因素。瀏覽器

另一個缺點就是隻能緩存文件,不能緩存一些常量,好比前端模板html片斷。緩存

爲此,咱們設計的webapp安裝更新程序,可以只在一個請求中下載全部資源文件內容。當資源有更新的時候,也是在一個請求中只獲取有更新的小粒度文件,而且能在客戶端緩存常量,如html片斷等。性能優化

三、自定義安裝更新程序

咱們想把資源細粒度的存儲在客戶端,當資源有更新的時候,客戶端能及時同步更新。要解決兩個主要問題:一、如何在客戶端存儲資源;二、如何及時獲取更新通知,並執行資源更新。

1)      客戶端資源存儲

咱們把資源序列化爲字符串,以鍵值對的方式存入客戶端本地存儲(localstorage)。好比基礎庫zepto.js文件,在本地存儲中的key爲zglobal/js/base/zepto.js,value就是zepto.js的被壓縮後的字符串內容了。同理,css文件,html前端模板都是同樣,適合作成base64編碼的圖片會以base64字符串的形式存在css文件。

在資源被引用的地方,若是是js文件,咱們會從本地存儲中取出js字符串內容,執行eval函數;若是是css文件,咱們會動態建立style元素,包含css內容,追加到HTMLDocument的head部分;若是是html前端模板,就在用到的地方,從本地存儲獲取前端模板字符串,而後調用模板方法進行渲染。

資源本地存儲示例片斷:

圖一

資源的引用方式sample code:

圖二

2)      獲取資源更新通知

實現資源更新要依賴於資源版本號。咱們把每一個資源緩存項都對應一個版本號(文件的md5值的前8位),整站全部資源緩存項對應一個總的版本號(全部資源緩存項的版本號的md5值)。

具體流程是:咱們把總版本號存入cookie,在一些入口url的服務器處理程序中,判斷客戶端cookie是否和當前服務器資源總版本號是否相同,若是相同,則跳過資源更新處理,直接啓動app,若是不一樣,說明有資源更新,此時,客戶端發送一個ajax請求,帶上當前客戶端每一個緩存項的版本號,向服務器獲取更新項,服務器對比客戶端每一個緩存項的版本號,就知道客戶端哪些資源是須要更新的,哪些資源是被刪除了的,所以,服務端就能只返回被更新了的資源。那麼,客戶端是如何拿到當前客戶端每一個緩存項的版本號呢?實際上是依賴於服務器響應客戶端ajax資源更新請求時,會包含每一個更新了的資源緩存項的名稱、版本號和資源內容字符串,客戶端拿到這個結果,會更新本地存儲中專門用來記錄更新後每一個資源項的版本號的一個本地存儲項,以一個json對象序列化後的字符串形式存在,所以客戶端發送的ajax請求,就是直接帶上這個json字符串便可。

程序流程:

圖三

圖三中的totalItemVersions就是全部細粒度資源緩存項的版本號記錄。在客戶端本地存儲中的key爲totalItemVersions,value是{「zglobal/html/frsMostTemplate.html」:」d6670285″,」zglobal/js/base/ajaxStore.js」:」68ce034f」,」zglobal/js/base/appBaseController.js」:」4083dd27″,」zglobal/js/base/appBaseModel.js」:」f1f806f1″,」zglobal/css/common/app.css」:」66153242″,」zglobal/css/common/base.css」:」2731733d」……….}

經過以上,咱們能發現,當服務器端無資源更新時,啓動的webapp將不會有網絡資源請求,直接加載本地資源,而後啓動app,後續只是app動態的json數據交互;當服務器有資源更新時,無論被更新的資源的多少,客戶端都是經過一個請求獲取僅更新的資源,而後加載資源,並啓動app。

四、本地build

瞭解了前面整個客戶端和服務器的交互以後,咱們可能會關心,這些資源在服務器端是如何生成並存儲的?這依賴於一個本地build過程。

在貼吧的前端開發中,是按不一樣模塊來開發的,不一樣模塊包含不一樣的功能,這樣能減小你們同時修改帶來的衝突。最後的上線,也是按修改的哪些模塊,只上線相應的模塊修改便可。

每一個模塊下都會有本地build腳本,只負責本模塊的build工做。對於安裝更新這塊來說,本地build輸出兩個文件,moduleVersion.php和cache.php。

cache.php就是當前模塊下全部的資源緩存項,每一個項的version就是資源文件的md5值的前8位,cache.php文件以下:

圖四

moduleVersion.php表示當前模塊的版本號,文件以下:

 

圖五

模塊版本號的計算方法是當前模塊下全部緩存項的版本號的總鏈接字符串的md5的前八位。這樣當任何一個資源文件有修改的話,資源文件的version將會改變,moduleVersion的值也會改變。

在「獲取資源更新通知」一節中,提到了整站全部資源緩存項的總版本號,這個版本號的計算方法是,全部模塊的版本號的總的鏈接字符串的md5。

圖六

五、使用建議

若是你們也在作無線webapp,建議不妨試試這種資源處理方式,將會有更少的資源請求,而且讓資源更快加載,給用戶帶來更好的體驗。

by gaofei

相關文章
相關標籤/搜索