cssやjsファイルのキャッシュ対策として更新日時のタイムスタンプをクリエとして自動付加。
cssやjsファイルがブラウザのキャッシュから読み込まれて更新が効かないときの対策として、PHPでファイル更新日時のタイムスタンプをクエリとしてファイル名に自動付加させる方法。
ブラウザは、キャッシュに同名ファイルがあると自動的にキャッシュ優先で読み込む場合があるので、ファイル名にそのファイルの更新日時を付加して同名ファイルと見做されないように対処する。
//同名ファイルはキャッシュ優先で更新が反映されないことがある
<link type="text/css" rel="stylesheet" href="style.css">
//ファイル更新日時をクエリとして付加してキャッシュ対策
<link type="text/css" rel="stylesheet" href="style.css?20210101010101">
ファイル名置換の関数を作成して該当箇所で実行
(1) ファイル更新日時のタイムスタンプを付与したファイル名に置換する関数を作成
- 引数として「ファイルのパス」を受け取る関数を作成。
- 引数で指定されたファイルがサーバー内に存在するか確認。(存在した場合のみ実行。)
- 「ファイルのパス」を、「ファイルのパス」+「?」+「ファイル最終更日時のタイムスタンプ」にして返す。
//置換用の関数
function ag2add_query($path){
if(file_exists($path)){
$new_path = $path.'?'.date('YmdHis', filemtime($path));
return $new_path;
}
}
file_exists(‘パス’) : 指定したパスのファイルあるいはディレクトリが存在するかどうかを調べる。存在すればtrue、無ければfalseを返す。
date(‘フォーマット’, ‘Unixタイムスタンプ’) : 指定したタイムスタンプを指定したフォーマットの文字列で返す。タイムスタンプの指定が無い場合、デフォルトタイムゾーンでの現在時刻(「time()」の値と同じ)が使用される。
filemtime(‘パス’) : 指定したパスのファイルの最終更新時刻をUnixタイムスタンプで返す。
(2) 関数を実行して出力
HTML内の任意の場所で、読み込むファイルのパスを引数に指定して上記の関数を実行して出力。
<link type="text/css" rel="stylesheet" href="<?php echo ag2add_query('style.css'); ?>">
<script type="text/javascript" src="<?php echo ag2add_query('js/foo.js'); ?>"></script>
WordPressで実装する場合
WordPressで実装する場合は、該当ファイルのサーバー内での絶対パスとテンプレート内での出力パスの違いに注意が必要。
- サーバー内での絶対パスは、サーバーサイドでの内部的なパス。
- テンプレートの出力パスは、サイト上に出力表示されるときのパス。(サイトのドメインでのURL。)
※ 処理の実行内容によってパスを考慮する必要がある。
(1) インラインで直接記述するとき
テンプレートの任意の場所に記述する。
//置換用関数
function ag2add_query($path){
$file_path = get_template_directory().'/'.$path;
if(file_exists($file_path)){
$new_path = get_template_directory_uri().'/'.$path.'?'.date('YmdHis', filemtime($file_path));
return $new_path;
}
}
ファイルを読み込みたい位置で上記の関数を実行。
//出力処理
<script type="text/javascript" src="<?php echo esc_url(ag2add_query('js/foo.js')); ?>"></script>
(2) システムが読み込むファイルへの対応
WordPressのシステムが自動的に読み込むcssとjsファイルにタイムスタンプを付加するには、function.phpにフィルターフックを記述して対応。
- フィルターフックで「stylesheet」か「script」の「src属性」が呼び出される度に、属性値のURLが自サイトかどうかを判定し、自サイトのリソースならクエリ付与の処理を実行。
- 「site_url()関数」(「WordPress アドレス (URL)」が取得できる組み込み関数)と「ABSPATH」(WordPressのインストールされたパスが代入されている定数)を使ってサーバー内の絶対パスにしてから該当ファイルのタムスタンプを取得。(「ABSPATH」のパスの末尾には「/」が付与されているので注意。)
- 元々の出力用のパスに、取得したタイムスタンプをクエリとして付与してから返す。
※ 「WordPress アドレス (URL)」と「サイトアドレス (URL)」が異なっている場合(WordPressをインストールしたディレクトリと公開ディレクトリが違う場合)は、「WordPress アドレス (URL)」でリソースのパスを取得する必要があるので注意。(「site_url()関数」は「WordPress アドレス (URL)」、「home_url()」は「サイトアドレス (URL)」が取得される。)
function ag2add_file_ver($path){
if(strpos($path, home_url()) !== false){
//自動で付加されるwordpressバージョン情報のクエリを削除
$path = preg_replace('/\?.+$/', '', $path);
//サイトURL部分をサーバー内パスに置換
$resource_path = str_replace(site_url('/'), ABSPATH, $path);
//URLにクエリパラメーターを付与
$new_path = $path.'?'.date('YmdHis', filemtime($resource_path));
}
return $new_path;
}
//フィルターフックで関数呼び出し
add_filter('style_loader_src', 'ag2add_file_ver');
add_filter('script_loader_src', 'ag2add_file_ver');
strpos(‘検索文字列’, ‘対象文字列’) : 対象文字列内から検索文字列を探し、文字列が見つかった位置を整数で返す。開始位置の場合は「0」を返すので、条件式では型まで判定する必要がある。検索文字列が見つからなかった場合はfalseを返す。strpos()関数は正規表現を使わないので処理が速い。
preg_replace(‘正規表現’, ‘置換後文字列’, ‘対象文字列’) : 対象文字列内のすべてのマッチした文字列を置換後文字列で置換。文字列ではなく配列の指定も可能。返り値はすべての該当箇所を置換した後の対象文字列。str_replace()関数の方が処理は速い。
str_replace(‘置換前文字列’, ‘置換後文字列’, ‘対象文字列’) : 対象文字列内のすべての置換前文字列を置換後文字列で置換。文字列ではなく配列の指定も可能。返り値はすべての該当箇所を置換した後の対象文字列。
すべてのリソースのキャッシュを許可しない場合
cssやjsファイルだけでなく、何の要素もキャッシュさせたくない場合の対処方法。
※ HTTPキャッシュに関するMozillaの公式ドキュメント。
すべてのリソースをキャッシュさせたくない場合は、header()関数を使ってHTTPヘッダーで「Cache-Control」ディレクティブを送信する。
- Cache-Control : HTTPのリクエストとレスポンスの両方でのキャッシュのためのディレクティブ(命令コマンド)。
- no-store : レスポンスをキャッシュに保存することはできず、新しいリソースがキャッシュされることを防ぐ。(すでにキャッシュ済みの古いリソースが存在している場合、そのキャッシュの利用は防げない。)
※ 画像などもキャッシュしなくなるので、毎回すべてのリソースのダウンロード処理が発生する。
※ Cache-ControlのMozillaの公式ドキュメント。
header('Cache-Control: no-store');
header(‘ヘッダー文字列’) : 生のHTTPヘッダーを送信する。
https://memo.ag2works.tokyo/post-1482/
cssやjsファイルのキャッシュ対策として更新日時のタイムスタンプをクリエとして自動付加。 | memo メモ [AG2WORKS]
<a href="https://memo.ag2works.tokyo/post-1482/" target="_blank" rel="noopener">cssやjsファイルのキャッシュ対策として更新日時のタイムスタンプをクリエとして自動付加。 | memo メモ [AG2WORKS]</a>
この記事へのコメント
コメントの書き込みはまだありません。