単一ページアプリでのブラウザーキャッシュの処理


27

単一ページアプリのWebブラウザキャッシュを適切に処理する方法を見つけようとしています。

私はかなり典型的なデザインを持っています:SPAを実装するいくつかのHTML、JS、CSSファイル、およびSPAによって消費されるJSONデータの束。更新をプッシュするときに問題が発生します:サイトの静的部分とJSONを生成するコードを同時に更新しますが、クライアントブラウザーには静的部分がキャッシュされていることが多いため、古いコードは新しいデータを処理しようとし、 (行われた変更に応じて)問題が発生する場合があります。(特に、IEは、再検証せずにキャッシュされたJSを使用することについて、ChromeまたはFirefoxよりも積極的です。)

これを処理する最良の方法は何ですか?

  1. JSONの変更に後方互換性があることを確認し、妥当な時間内にブラウザーのキャッシュが期限切れになると仮定します。
  2. 静的JSとJSONの両方に何らかのバージョン番号を埋め込み、window.location.reload(true);一致しない場合は実行します。
  3. ヘッダーの適切な組み合わせ(must-revalidateまたはno-cache何でも; ソース はこれを行う方法によって異なります)を把握して、サイトをロードするための余分な往復を意味する場合でも、ブラウザーがすべてのロードで常にすべてのリソースを再検証するようにします。
  4. 更新をプッシュするときに静的コンテンツが期限切れになるように、キャッシュコントロールと期限切れヘッダーをマイクロ管理します。
  5. 他に何か?

1
あなたの環境が同僚からの悪(iOSの)である場合、組み込みのWebブラウザコントロールで#3と#4が予期せず失敗することを聞いたことがあります。#1と#2はアプリレベルの選択になりますが、それでも他のリソースまたは部分的なリソースロードのキャッシュの問題を引き起こす可能性があります(?)。本番用のコードで確実に機能するのは、yoururl.htmlをフェッチすることだけです。<SomeTimeStamp>を使用すると、ほとんどのキャッシュメカニズムが偽装されます。ボーナス:アトミックに成功または失敗するように、Webアプリ全体をファイルにロールします。欠点:ローカルリンクで最適に動作します。あなたのマイレージは異なる場合があります。がんばろう!
Jトラナ14

2
リソースのURLパラメーターとしてバージョン番号またはタイムスタンプを使用するための+1。
9000 14

回答:


14

キャッシュ無効化ソリューションが必要です。キャッシュ無効化の役割は次のとおりです。

  1. コンテンツの内容に応じて、リソースの名前を一意の名前に変更します。
  2. それらのリソースへのすべての参照を更新します。

Gruntベースのプロジェクトでは、grunt-revを使用して、更新する必要があるすべてのファイルに、そのコンテンツに基づいて一意の名前が付けられるようにするのが一般的です。

JSONファイルがJavascript内の参照とともにキャッシュ無効化ファイル名を取得するようにすると、クライアントは常にJavascriptが予期するJSONファイルをロードします。

ハッシュベースのファイル命名の利点は、変更されていないファイルがキャッシュ無効化後に同じファイル名を取得するため、ブラウザは変更されていないキャッシュされたコンテンツを安全に使用し続けることができることです。

明らかに、これはプロジェクトのプロダクションビルドの一部として自動化したい種類なので、手動でファイル名と参照の変更を追跡する必要はありません。


2
斜体の「キャッシュ無効化」ビットの+1。これにより、実際にこのようなものを生産的にGoogleで検索することができます。
ザッククス14

@Ted Percival-Yeomanフレームワークはこれを行いますが、私はこれを使用していますが、問題が発生しています。新しいビルドをリリースすると、ブラウザのindex.htmlに古いファイルへの参照がキャッシュされている場合があり、ブラウザでエラーが発生します。どうすれば修正できますか?(A.)すべての古いファイル名を新しいファイル名にシンボリックリンクします(これは動作します)(B.)index.htmlにno-cacheヘッダーを追加します(ただし、これは常に尊重されます)(C.).htaccessを追加して、改訂されたファイルを認識します(。 - > main.jsすなわち12345.main.js)とベース1の検索
TIMH

5

適切なヘッダーとともにif-modified-since + last-modifiedor if-none-match + etagヘッダーを使用できますcache-control。(ブラウザのバグが存在する可能性がありますが、最近のブラウザでは管理できないものはありません。)

ファイルが静的な場合はif-modified-since、適切に構成されたHTTPサーバーで自動的に実行できるため、を使用することをお勧めします。ファイルが最後のダウンロード以降に変更されていない場合、304を送り返す必要があります。

あなたの#1と#2が長期的には機能するとは思わない。#3または#4が機能します。#3は簡単ですが、この問題に対処する方法を一度だけ学習する必要があります。だから私があなたなら#4を試してみますが、解決策は顧客が使用するブラウザに依存するかもしれません...例えば、IE8にはajaxキャッシュの更新などの問題があります...


2

SPAにJava Servlet Filterを含めることができる場合、有効なソリューションは次のとおりです:CorrectBrowserCacheHandlerFilter.java

基本的に、ブラウザが静的ファイルを要求すると、サーバーはすべての要求を同じものにリダイレクトしますが?v=azErT、ターゲットの静的ファイルのコンテンツに依存するハッシュクエリパラメーター(たとえば)を使用します。

これを行うと、ブラウザはindex.htmlたとえばで宣言された静的ファイルをキャッシュしません(常にを受け取るため302 Moved Temporarily)が、ハッシュバージョンのファイルのみをキャッシュします(サーバーが200それらに応答します)。そのため、ブラウザのキャッシュは、ハッシュバージョンを持つ静的ファイルに対して効率的に使用されます。

免責事項:私はの著者ですCorrectBrowserCacheHandlerFilter.java

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.