2016-01-30 47 views
2

我已經構建了一個基本上基於指令的AngularJS HTML5應用程序。每個指令將使用templateUrl語法從另一個文件加載它的模板。瀏覽器緩存的部分

應用程序是一個單頁的應用程序,讓我們假裝它通過http://prod/index.html的訪問,並且加載該頁面時,指令將然後加載http://prod/partials/directive-a.html


我有問題推出的新版本中,當該網站到我的生產環境。瀏覽器繼續使用先前版本的緩存資產。


例如,如果我定位到http://prod,所有的資產從以前的版本中。如果我強制刷新頁面(CTRL+F5),index.html頁面將從服務器重新加載並反映任何更改。

這是的不是導致瀏覽器刷新partials/directive-a.html。因此,新的index.html頁面仍顯示舊的directive-a.html

如果我在瀏覽器地址欄中導航到完整的部分HTML文件(partials/directive-a.html),則向我顯示舊版本的部分文件。通過硬刷新部分頁面,將顯示該部分的正確(新)版本,並且當index.html上的指令被重新加載時也被更新。


我有什麼機制可以阻止部分緩存嗎?

我見過關於追加時間戳到查詢參數的評論,但這似乎過於笨重,把我所有的指令和路線。

+0

我認爲通過在應用程序配置中添加無緩存頭,通過平臺軟件服務器端的構建方式來禁用緩存? 。 –

+0

@PankajParkar當然可能,HTML服務器正在通過Apache httpd銷售。這顯然會影響性能(特別是在移動設備上),但我可能能夠忍受這一點...... – jwa

+0

是的..這可能會影響移動設備的性能。但我認爲這可能有助於http://stackoverflow.com/a/11724596/2435473 –

回答

1

我還沒有測試過,看看這個工程(發現快速谷歌搜索),但我認爲它應該。它正在裝飾$http服務,以便任何請求都有一個cache-buster添加到url中。您可能需要將邏輯更改爲僅裝飾'partials/'文件夾中的網址。

anglar.module('myApp',['ui']).config(["$provide", function($provide) { 
    return $provide.decorator("$http", ["$delegate", function($delegate) { 
     var get = $delegate.get; 
     $delegate.get = function(url, config) { 
      // Check is to avoid breaking AngularUI ui-bootstrap-tpls.js: "template/accordion/accordion-group.html" 
      if (!~url.indexOf('template/')) { 
       // Append ?v=[cacheBustVersion] to url 
       url += (url.indexOf("?") === -1 ? "?" : "&"); 
       url += "v=" + cacheBustVersion; 
      } 
      return get(url, config); 
     }; 
     return $delegate; 
    }]); 
}]); 

https://gist.github.com/ProLoser/6181026

或者編譯所有的泛音成一個單一templates.js文件填充模板緩存,然後你必須在所有的模板沒有實際的HTTP請求。如果您使用gulp構建您的應用程序,那麼可以使用各種插件模塊(例如gulp-angular-templatecachegulp-angular-templates)。

+0

可能的問題:'ui-bootstrap-tpls.js'不是唯一可以破解的。 – rzelek

+1

@ArekŻ[email protected]這就是爲什麼我建議改變代碼只能處理'partials /'文件夾的請求。 – Duncan

+0

你是對的,但你不能保證第三方庫不會使用'partials /'推送'$ templateCache'服務。無論如何,這個解決方案非常棒,因爲你不會失去緩存機制。 – rzelek

2

@Duncan給了你很棒的方式來處理模板,但我認爲這不是唯一的問題。請記住關於高速緩存js,cssindex.html

簡單的解決方案 如果你想緩存簡單的問題(幾乎理想的)解決方案,可以強制服務器在第一個請求設置會話cookie(用於index.html)。瀏覽器將緩存htmljs會話的長度。你仍然有部分緩存支持,沒有問題。

# First response header will set session id: 
Set-Cookie:JSESSIONID=0E9AAA7D661A3E100C8EE9F421541B91; Expires=Sun, 29-Jan-2017 14:25:25 GMT; Path=/; HttpOnly 

# Next browser request will contain session id from first response. 
Cookie:JSESSIONID=0E9AAA7D661A3E100C8EE9F421541B91 

複雜的解決方案

您應該考慮使用自定義標題爲服務角資產。您可以在apache內使用mod_expires

ExpiresByType text/html        "access plus 0 seconds" 
ExpiresByType application/javascript    "access plus 0 seconds" 
ExpiresByType text/css        "access plus 0 seconds" 
... 

該解決方案的問題是丟失緩存機制。返回的用戶不會更快地加載您的網站,您的服務器將會體驗到更多的使用。您可能會遇到性能問題。

您可以提高該解決方案通過建機制:

  1. CONCAT你的應用程序的js到application.js
  2. 縮小/醜化application.js
  3. 變化application.jsapplication.[unique-id].js
  4. 變化OCCURENCES在index.html

The sa我適用於css和第三方庫。

那之後,你就能夠改變

ExpiresByType text/html        "access plus 0 seconds" 
ExpiresByType application/javascript    "access plus 1 year" 
ExpiresByType text/css        "access plus 1 year" 
... 

基於GruntGulp顯然,有自動化解決方案。就個人而言,我可以推薦https://github.com/yeoman/generator-angular

這兩個解決方案都適用於我當前的應用程序。

+0

'ExpiresByType text/html「訪問加0秒」'對我們來說是一個巨大的幫助,謝謝!我們使用Shibboleth保護我們Angular應用程序的某些視圖,如果瀏覽器加載頁面的緩存版本,Shibboleth指令永遠不會觸發。這似乎解決了這個問題。 – JLewkovich