

MacOSX SierraにHomebrewでapache2を入れ、png画像とhtmlを配置しています。

画像をキャッシュしたいと思い、以下のようにhttpd.confの設定をしました。  
強制的にdiskキャッシュするためのモジュールのインポートと、diskキャッシュの設定と、ヘッダの設定です。

Last-
modefiedとExpireがレスポンスヘッダに乗っていないとキャッシュされないと(どこかで)見たためこちらも追記しており、両方正常にレスポンスヘッダに乗っていることを確認しています。

[code]

    LoadModule cache_module modules/mod_cache.so
    LoadModule disk_cache_module modules/mod_disk_cache.so
    
    <IfModule mod_cache.so>
        <IfModule mod_disk_cache.so>
            CacheRoot /tmp/cache
            CacheEnable disk /
            CacheIgnoreCacheControl On
            CacheIgnoreNoLastMod On
            CacheDefaultExpire 86400
            CacheMaxExpire 172800
        </IfModule>
    </IfModule>
    
    <IfModule mod_expires.c>
      ExpiresActive on
      ExpiresDefault 
      ExpiresByType image/png 
      <IfModule mod_headers.c>
        Header append Cache-Control "public, max-age=86400"
        Header set Expires "Mon, 26 Jul 2017 05:00:00 GMT"
      </IfModule>
    </IfModule>
    
[/code]

その後、/tmp/cacheを作成しパーミッションを777にしてapacheをrestartし、chromeのdeveloperツールのネットワークを開き、htmlのaタグから画像にアクセスし、1回目でStatus
200、2回目で(from disk
cache)と表示されていることを確認しているのですが/tmp/cacheには何もファイルが残っていません。また、chromeを再起動してから再び画像にアクセスするとStatus200となります。

Webサーバの設定でブラウザを再起動してもローカルのキャッシュを表示する方法はありますか？

1回目のアクセス時のレスポンスヘッダです。

[![1回目](https://i.stack.imgur.com/LyrSAm.png)](https://i.stack.imgur.com/LyrSA.png)

２回目以降です。  
[![2回目以降です](https://i.stack.imgur.com/jwXVkm.png)](https://i.stack.imgur.com/jwXVk.png)

↓  
ご指摘頂き、apacheの設定の仕方が間違っていたことがわかりました。

[code]

        Header append Cache-Control "public, max-age=86400"
    
[/code]

を

[code]

        Header set Cache-Control "public, max-age=86400"
    
[/code]

とすることでChromeを再起動させてもapacheにアクセスログが表示されないことを確認しました。  
ただ、safariではアクセスがされてしまい、固有のバグのようでした。  
ローカルキャッシュの活用を考えていますが、やりたいこととしては必要のない画像取得の通信を出来るだけ減らしたい、更新のない同じ画像を何度もapacheからダウンロードさせるのは避けたいが更新があれば通信させるということです。  
オフラインでも動くことは求めておらず、画像はバナーや商品画像など様々なものがあるためマニフェストファイルに画像を指定するApplicationCacheよりローカルストレージを使い、キャッシュを更新したいときはAPIから更新フラグを受け取り、更新する場合はclearCacheするという方法を用いたいと思います。

↓

と思ったのですがAPIからキャッシュクリアするフラグを入れるのは悪手だということがわかりました。  
どれだけの期間フラグをtrueにするかの問題とか、フラグがtrueになっている間はアプリを起動するたびにキャッシュ削除→画像再取得という状態になってしまうので、画像URLを変更しようと思います。


CC BY-SA 3.0
2017-03-06T23:13:34.133
33151
2017-03-11T19:19:16.053
2017-03-11T19:19:16.053
20920
20920
question
apache mod-cache
apacheのキャッシュが効きません


サーバーサイドキャッシュとクライアントサイドキャッシュは別物です。それぞれ区別して考える必要があります。一度指摘しましたが、修正してもなお「サーバーサイドキャッシュの設定を行ったがクライアントサイドキャッシュが行われていない」旨が質問されていて、質問者さん自身が何を求めているのかわかっていない印象を受けます。

まずサーバーサイドキャッシュについてですが、`/tmp/cache`ディレクトリに対して何を求めているのでしょうか？
質問文からはディスクの別領域に置かれている画像ファイルをこのディレクトリ下にコピーされることを期待しているように読み取れますが、コピーする意義がありません。  
動的に生成されたコンテンツや`Content-Encoding:
gzip`などで圧縮されたコンテンツが置かれる場所と考えるべきです。（IISは後者も置いていましたがApacheは置かなかったような…うろ覚えです。）

次にクライアントサイドキャッシュについてですが、設定内容だけでなくブラウザー側で受信したレスポンスヘッダーも提示していただかないことにはわかりません。  
レスポンスヘッダーとは全く別アプローチの[アプリケーションキャッシュ](https://developer.mozilla.org/ja/docs/Web/HTML/Using_the_application_cache)という機構もあります。こちらも一つの選択肢としてお考え下さい。

* * *

レスポンスヘッダーの画像を確認しましたが

>
[code]

>     Header append Cache-Control "public, max-age=86400"
>     Header set Expires "Mon, 26 Jul 2017 05:00:00 GMT"
>  
[/code]

のヘッダーが含まれていません。まずは設定内容が正しく反映できているかを確認すべきですし、それができていなければあらゆる設定に意味を持たないと思います。

>
> アプリケーションキャッシュはサ‌​ーバ側で更新することが難しい(間違った画‌​像を配信した場合にすぐ更新するのが難しい‌​)と聞いてローカルストレージを優先して試‌​そうと考えています

そもそもWebサーバーと通信しないようにしたいという質問だったはずです。通信しない以上、どのような方法であれWebサーバー側での更新内容を知ることはできません。  
最初に指摘しましたが、 **どこで何をキャッシュさせたいのか考え直すことをお勧めします。**


CC BY-SA 3.0
2017-03-07T01:08:34.420
33153
2017-03-07T02:59:28.590
2017-03-07T02:59:28.590
4236
4236
33151
answer


なぜ mod_expires に加えて手動で `Header set` をしているのですか？

mod_expiresはファイル形式に応じて、また「n日後」といったわかりやすい指定で Expires や max-age
を設定できるモジュールです。例えば次の記述でPNG画像に対してキャッシュ期限が「アクセスから1ヶ月」となるヘッダが出力されるはずです。

[code]

    <IfModule mod_expires.c>
      ExpiresActive on
      ExpiresByType image/png "access plus 1 months"
    </IfModule mod_expires.c>
    
[/code]

このように長いExpiresを指定した場合キャッシュの破棄をどうするかですが、よく使われる方法として、画像の更新時は画像のURLを変更する、というものがあります。単にファイル名を変えてもいいですし、クエリ文字列にタイムスタンプやハッシュ値を埋め込んでもよいです。

例: `foo.png?v=20170210` ⇒ `foo.png?v=20170308`

こうすれば更新前とは違うURLなので、既存のキャッシュが使われることはありません。

ちなみに、Expiresが切れるまでの間は更新確認も行われないため、Last-Modified や ETag
が使われることもありません。URLの更新が面倒なら、逆にExpiresを0にして`If-None-Match` や `If-Modified-Since`
で妥協するのも手です。完全に通信をなくすことはできませんが。

* * *

次に localStorage
ですが、これは非同期APIを持たないので、保存・取り出しのどちらもUIスレッドをブロックします。格納できるデータの量も5MB程度とさほど多くありません。IndexedDBならいくぶんマシですが…。

  * [ローカルストレージに簡単な解決策はない | Mozilla Developer Street (modest)  
](https://dev.mozilla.jp/2012/03/there-is-no-simple-solution-for-local-
storage/)

  * [モダンブラウザのストレージ容量と調査方法まとめ - HTML5 Rocks](https://www.html5rocks.com/ja/tutorials/offline/quota-research/)

キャッシュ絡みの問題でよく使われる「ブラウザのキャッシュ削除機能」「スーパーリロード」が使えない、ユーザー側のストレージでキャッシュ用でない領域を消費する、といった細かい話も。

またマニフェストファイルを使う ApplicationCache は既に廃止する方向で進んでいるのですが、その後継とされる ServiceWorker
のキャッシュ機能なら、JavaScriptを使って柔軟に制御することができます。が、こちらはブラウザの対応状況が芳しくないです。

これらのことを踏まえて、それでもExpires（あるいは `If-**`）では不十分なのかを検討された方がいいように思います。


CC BY-SA 3.0
2017-03-08T03:28:25.917
33182
2017-03-08T05:42:12.717
2017-03-08T05:42:12.717
8000
8000
33151
answer