CSSやJavascrtiptが更新されないキャッシュ問題を Ant で解決する

2017年8月6日Java,開発

おはようございます。

WEBシステムでよく問題になる CSSやJavascriptを変更しても反映されない現象で困ったことはありませんか?

大体の場合、キャッシュが残ってしまっているのが原因だと思いますが、
そのキャッシュをどうにかするために、Antを使って小細工をしてみました。

基本的に Java の WEBシステムを想定しています。

スポンサーリンク

Cache(キャッシュ)とは

ここでいうキャッシュとは、ブラウザにキャッシュされる一時的なデータを指しています。
(他にPCのキャッシュメモリーを指すこともある)

どちらも基本的に目的?動作は同じで、処理の速度を高速化させることができます。
ブラウザキャッシュであれば、毎回インターネット上のWEBサーバーからデータ(HTMLなど)をダウンロードして表示するのではなく、
同じ内容であればキャッシュを利用することでページの表示を高速化しています。

デメリットをあげるとするならば、次にあげるキャッシュ問題というのがあるかと思います。

キャッシュ問題

WEBシステムで
外部ファイルに定義した CSSやJavascript を修正して本番WEBサーバにデプロイした際に
顧客が利用するブラウザに、CSSやJavascriptがキャッシュされてしまっている場合にうまく最新の状態になってくれない、
最悪の場合は Javascript でエラーが発生してしまって動作しなくなるなんてことが起こります。

この場合、ブラウザの機能で強制リロードという操作をすると簡単に解決できるのですが、
これを知らないユーザが多いため、ユーザーからどうにかしろと言われることが多いです。

もうほとんど間違いなく言われますよね。文句を。

対応方法

対応についてはおそらく次の方法が一般的なのかと思う。

  1. HTMLに制御文を仕込む
    HTML(メタタグ)で制御、そもそもデータをキャッシュさせないって方法がある。
    ただし、そもそもキャッシュ機能はページ読込の速度を早くする目的があるため
    あんまりよろしくない。と個人的には思う。
  2. WEBサーバ側で制御
    1番と似ているが、WEBサーバ側でクライアントにレスポンスを返す際に
    HTMLヘッダーという情報に、キャッシュさせないでねって情報を含めることで
    ブラウザを制御する。
    これも1番同様あんまりよろしくない。
  3. 外部ファイルの読み込みに細工する
    クエリパラメータというものを用い、外部ファイルを読み込む際に細工をする。
    変更したCSSや Javascript を読み込むページで、
    読込の記述にクエリパラメータを付加することでキャッシュされたデータとは
    違うものですよってブラウザに認識させる方法。
    この方法であれば、他のキャッシュデータについてはそのままキャッシュを使ってくれる。
    ただし、手動で数あるページを修正していくと必ずミス(修正漏れ)が発生する。

基本的には3番がいいと思うので、
自動でクエリパラメータを付けるバッチを組み込むことにしました。

CSSおよびJavascript を読み込んでいる箇所すべてにクエリパラメータを付与しておき、リリースするモジュールを作成する際に Ant で文字列をタイムスタンプに置換する。
というようにしておけば必ず最新の外部ファイルを読み込ませることができるはず。

仕掛け

クエリパラメータを付与

外部ファイルの読み込み部分に次のようなクエリパラメータを付与します。

?bld=BUILD_DATE

JSPのサンプル

<!DOCTYPE html>
<html>
        <head>
                <title>ログイン画面</title>
                <meta charset="UTF-8">
                <meta http-equiv="X-UA-Compatible" content="IE=edge">
                <link rel="stylesheet" type="text/css" href="css/login.css?bld=BUILD_DATE" media="all">
                <script type="text/javascript" src="js/login.js?bld=BUILD_DATE"></script>
        </head>
        <body>
        <!-- コンテンツ -->
        
        </body>
</html>

Antファイルの作成

Build.properties

webapp.dir=src/main/webapp/

Build.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="mpms-web" default="replace-include-file-timestamp" basedir=".">
            <property file="build.properties" />
            <target name="replace-include-file-timestamp">
                    <echo message="replace-include-file-timestamp start." />
                    <tstamp>
                        <format property="timestamp" pattern="yyyyMMddHHmmss" />
                    </tstamp>
                    <echo message="Build Date = ${timestamp}" />
                    <replace dir="${webapp.dir}/WEB-INF/jsp" token="BUILD_DATE" value="${timestamp}" encoding="UTF-8">
                        <include name="**/*.jsp" />
                    </replace>
                    <echo message="replace-include-file-timestamp end." />
            </target>
    </project>

Antタスクの呼び出し

    Ant で実行
    ant -f build.xml replace-include-file-timestamp
    
    Maven で実行
    cmd /c "mvn antrun:run -Dtarget=replace-include-file-timestamp"

コマンドを実行すると、BUILD_DATE となっている箇所が、実行日時「yyyyMMddHHmmss」に置き換わります。

まとめ

最善の方法かはわかりませんが、
ひとまずこういった仕組みを入れておけばいちいち顧客からの問い合わせにキャッシュクリアしてくださいって言わなくて済みますね。

ではでは。

スポンサーリンク


関連するコンテンツ

2017年8月6日Java,開発WEBサービス,トラブルシューティング

Posted by doradora