【ASP.NET MVC】 ASP.NET MVCで、ブラウザに、JavaScript/CSS/画像をキャッシュさせないためには...

はじめに

 * 開発時 や リリース後のアップデート などで、ブラウザに古いJavaScript/CSSなどがキャッシュとして
   残っていることがあり、それにより、最新版のモジュールが正しく動作しない事がある。
 * キャッシュを抑制するために、Cache-Control : no-cacheなどで対策してもダメな時が多々ある

って事で対策を考える

対策案

* 大きく分けて2点
[1] ファイル名にバージョンを付加させて管理。(例:<script src="./jquery-1.10.2.js"></script>)
  => ただし、この方法だと、リリースバージョンを切らない開発時だとキャッシュに残ってしまう
  => ソース管理している場合、バージョンごとにファイルができるのはイヤ

[2] クエリー文字列を付加する(例:<script src="./jquery.js?v=xxxxx"></script>)
  => こっちがいいかと
  => クエリー文字列に付加させる情報としては、以下のようなものが考えられる

【クエリー文字列に付加させる情報候補】
 2-1) ファイル更新日時 (例:<script src="./jquery.js?date=201602252201413111"></script>)
 2-2) 現在日付
 2-3) バージョン(例:<script src="./jquery.js?ver=1_10_2"></script>)
 2-4) ランダム数・ハッシュ値
などなど

  => 個人的には、必要時にはファイルを更新し、それ以外はキャッシュを使う方が、
     効率がいいわけなので、「2-1) ファイル更新日時」がいいと思う

 * 何故、クエリー付加させたらキャッシュクリアになるのかは以下のサイトを参照。
http://www.koikikukan.com/archives/2011/08/29-015555.php

ASP.NET MVCで実装するには?

[1] クエリー文字列にファイル更新日時を付加させる
 1-1) ビュー内で実装する
 1-2) ビュー以外(BundleConfigクラスなど)で実装する

[2] Bundles.ResolveBundleUrlメソッドを使う
    # API仕様については、以下のサイトを参照。ハッシュ値を使うらしい。
https://msdn.microsoft.com/ja-jp/library/system.web.optimization.bundlecollection.resolvebundleurl.aspx

サンプル

■ 実装1:ビュー内で実装する

@Code
    ViewData("Title") = "Index"

    ' ★ここ★
    Dim filePath = Server.MapPath(Url.Content("~/Scripts/jquery-1.10.2.js"))
    Dim fileDate = System.IO.File.GetLastWriteTime(filePath).ToString("yyyyMMddHHmmssfff")
End Code
<script src="@Url.Content("~/Scripts/HelloWorld.js?date=" & fileDate)" type="text/javascript"></script>
・・・略・・・

出力結果

<script src="/Scripts/HelloWorld.js?date=20160104220752149" type="text/javascript"></script>

■ 実装2:ビュー以外で実装する

Imports System.Web.Optimization

Public Module BundleConfig
    Public Sub RegisterBundles(ByVal bundles As BundleCollection)


        bundles.Add(New ScriptBundle("~/bundles/jquery").Include(
                "~/Scripts/jquery-{version}.js"))

        ' ★ここ★
        Dim filePath = Hosting.HostingEnvironment.MapPath("~/Scripts/HelloWorld.js")
        Dim fileDate = System.IO.File.GetLastWriteTime(filePath).ToString("yyyyMMddHHmmssfff")
        bundles.Add(New ScriptBundle("~/bundles/jsHello").Include(
                "~/Scripts/HelloWorld.js?date=" & fileDate))
    End Sub
End Module

■ 実装3:Bundles.ResolveBundleUrlメソッドを使う

Bundleについては、以下の関連記事を参照のこと
http://blogs.yahoo.co.jp/dk521123/35704775.html
<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/jsHello")" type="text/javascript"></script>

出力結果

* 軽く実験したが毎回違うハッシュ値ではなく、中身のJSに変更になったら変わるが、変更がなかったら同じハッシュ値だった
<script src="/bundles/jsHello?v=BZGaXsRK3rFdbpY0k8ak1Ls0nJDWwbTUS4hURH1dUIo1" type="text/javascript"></script>


関連記事

Minify & BundleをASP.NET MVC で使う

http://blogs.yahoo.co.jp/dk521123/35704775.html

ASP.NET】URLなどの扱いあれこれ(取得など)

http://blogs.yahoo.co.jp/dk521123/26988494.html