2012年10月9日 星期二

使用JavaScript Framework所延伸瀏覽器Cache JavaScript File的問題

    在目前JavaScript Framework(如:ExtJQueryAjaxControlToolkit等)大量使用的時代,對開發人員而言,瀏覽器 Cache 網頁和JavaScript File(下文以JS File簡稱)不僅僅導致開發人員開發上的問題,更會使得使用者因為無法正確使用更新後的版本,而無法正常使用功能!本文將不再老生常談一些基本知識,如果大家有需要會再另寫文章。
    我們都知道,如果要使網頁或者JS File在每次Request時,都會自動向Server取回檔案,必須使用以下的metadata資訊:

<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="cache-control" content="no-cache"/>
<meta http-equiv="expires" content="0"/>

cache-control為例,重點在於," Cache-Control: no-cache""Cache-Control: max-age=0"到底有甚麼區別?乍看之下好像沒有甚麼差異性,主要差異在於"max-age=0"它只會去跟Server驗證(可以參考http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3原文說明)是否有過期,如果ResponseDate Header判斷後不需要重新取回,那就會使用Cache,而"no-cache"則是每次request都會去重新取回檔案(可以參考http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.6原文說明),所以如果使用"max-age=0"不見得會更新你的資料!
    但是這一切如果是這樣那就太好了!那是不是只要設定no-cache就可以自動更新檔案?很不幸的,不同瀏覽器下所抓到的Request Header,其Cache-Control有時會呈現max-age=0的方式,所以會發現網頁或者JS File沒有被更新,IE 9下更測出明明有更新過檔案,但是Request HeaderStatus Code一直呈現304(代表直接使用Cache200代表會從伺服器抓取)!這樣的結果代表瀏覽器會不遵循直接加在head中的metadata資訊,Google Chrome直到最新版本仍會有不遵循Cache-Control的設定,隨便向Google查詢相關問題就會跑出一堆結果。
    那如果完全使用JavaScript Framework建構的AJAX網站情況是不是也一樣呢?如果完全使用JavaScript Framework建構,例如:Extjs,時常會使用autoLoad的方式來載入其它頁面( EX: autoLoad: { url: URLPath, scripts: true,nocache:true }),在有加metadataExtjsnocache屬性的情況下,有時會發現,不管如何大力按F5瀏覽器依舊使用Cache!所以在開發環境下,通常開發人員會強制讓瀏覽器直接重新下載JS File,以確保開發過程中的順利,但是如果現在角色是Client端這又該如何?歷史是不是一定又會重演?上述加metadata和加Extjsnocache屬性的方式好像又不管用,就算更新網頁,但是就是不會更新JS File
    有鍵於此,建議加上參數來讓瀏覽器自動從Server重新載入JS File

<script type="text/javascript" src="/JSFilePath.js?r=1234"></script>

但是這樣到最後不是一樣意思嗎!是否可以隨機產生亂數讓每一次的數值都可以不一樣,這時就需要使用隨機產生亂數和動態加載JS File,動態加載JS File在網路上有很多五花八門的使用方式,但是因為只需要簡單的載入JS File,故我們可以使用以下的方式動態加載JS File並且亂數產生數值,適用各種瀏覽器:

<script type="text/javascript>
   var DnyScript = document.createElement('script');
   DnyScript.setAttribute('type', 'text/javascript');
   DnyScript.setAttribute('src', '/JSFilePath.js?r=' +Math.floor(Math.random() * 1000 + 1));
   document.body.appendChild(DnyScript);
</script>

如此便可以讓瀏覽器強制更新JS File,並且可以像以往一樣自行決定JS FileHTML中的執行順序和各JS File間的執行順序,但是唯一的缺點就是每次的Request會需要額外的流量,但這就是正確性跟流量的取捨問題,不過可以藉由壓縮和混淆JS File的方式來減少JS File的大小。另外值得一提的是,使用此種方式對於JS File的保護會有一定程度上的幫助,這地方各位可以思考看看!
     如果本文有不足或錯誤之處,希望各方大老不吝指教,文中若有其他需要另開文章說明,各位不嫌棄本人的文筆及技術再煩請告知,在空閒之餘會另開文章發表拙見!


轉貼請註明出處,最好直接使用聯結轉貼!Thanks~
作者: Samuel-林靖傑
日期:2011/06/28

沒有留言:

張貼留言