ユーザー側のブラウザで最新のCSS/JavaScriptを読み込ませる方法

CSSやJavaScriptのような静的なファイルはユーザーが使用しているブラウザにキャッシュされます。キャッシュが残っていると基本的にはそちらが優先して読み込まれるため、せっかくファイルを更新しても変更内容が適用されず、予期せぬバグを引き起こしたりします。これを防ぐ手段として Cache Busting と呼ばれる方法があります。

Cache Busting

キャッシュバスティングを利用するとスーパーリロードを実行したり、ブラウザのキャッシュをクリアせずに、最新のファイルをサーバーにリクエストさせることができます。

キャッシュバスティングには次の3つの方法があります。

  • ファイル名にバージョン管理番号を入れる(例:script.v2.js)
  • ファイルパスにバージョン管理番号を入れる(例:/v2/script.js)
  • クエリ文字を使ってバージョン管理番号を付与する(例:script.js?ver=2)

ファイル名またはファイルパスを利用した方法が推奨されており、クエリ文字を使う方法は避けたほうが良いと言われています。理由は、サーバー側(プロキシやCDN)でクエリ文字を利用したファイルをキャッシュできない場合があるからです。常に最新のファイルを読み込むことになるため、リクエスト数が嵩みます。できれば、更新された時だけ最新のファイルを読み込ませたいですよね。

しかしクエリ文字を使うのが最も手軽なので、今回はその方法を試します。

自動でクエリ文字を付与するスクリプト

JavaScriptファイルを読み込む時、scriptタグにsrcを指定しますが、その際にクエリ文字を付与します。

<script src="script.js"></script>

例1:
<script src="script.js?ver=20180604"></script>

例2:
<script src="script.js?ver=1528236442560"></script>

次のようなスクリプトで現在の日付を自動付与してみました。bodyタグの最後に、クエリを付与したscriptタグを吐き出してくれます。大元のファイル名を変更しなくていいので楽チンです。

<script>
var today = new Date()
var year = today.getFullYear()
var month= today.getMonth() + 1
var date = today.getDate()
if (month < 10) {
month = "0" + month
}
if (date < 10) {
date = "0" + date
}
var versioningNum = "" + year + month + date
var jsURL = 'js/custom.js?ver=' + versioningNum
var jsElement=document.createElement('script')
jsElement.setAttribute('src', jsURL)
document.getElementsByTagName("body")[0].appendChild(jsElement)
</script>

CSSの場合は body ではなく head に出力するように修正すればおっけーです。

1日になんども更新することがあるなら、日付ではなく、次のように getTime() を使って時間で管理するのがいいですね。

<script>
var versioningNum = new Date().getTime()
var jsURL = '../../portfolio/js/custom.js?ver=' + versioningNum
var jsElement=document.createElement('script')
jsElement.setAttribute('src', jsURL)
document.getElementsByTagName("body")[0].appendChild(jsElement)
</script>

まとめ

クエリ文字を利用した Cache Busting を試しました。これでキャッシュによるバグを抑えることができます。やったね!