#032
posted on 2021.04.02

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) ファイル更新日時のタイムスタンプを付与したファイル名に置換する関数を作成

  1. 引数として「ファイルのパス」を受け取る関数を作成。
  2. 引数で指定されたファイルがサーバー内に存在するか確認。(存在した場合のみ実行。)
  3. 「ファイルのパス」を、「ファイルのパス」+「?」+「ファイル最終更日時のタイムスタンプ」にして返す。
//置換用の関数
function ag2add_query($path){
	if(file_exists($path)){
		$new_path = $path.'?'.date('YmdHis', filemtime($path));
		return $new_path;
	}
}

file_exists(‘パス’) : 指定したパスのファイルあるいはディレクトリが存在するかどうかを調べる。存在すればtrue、無ければfalseを返す。

date(‘フォーマット’, ‘タイムスタンプ’) : 指定したタイムスタンプを指定したフォーマットで返す。タイムスタンプの指定が無ければ、デフォルトタイムゾーンでの現在時刻を指定フォーマットで返す。

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にフィルターフックを記述して対応。

  1. フィルターフックで「stylesheet」か「script」の「src属性」が呼び出される度に、属性値のURLが自サイトかどうかを判定し、自サイトのリソースならクエリ付与の処理を実行。
  2. 「ABSPATH」(WordPressのインストールされたパスが代入されている定数)を使ってサーバー内の絶対パスにしてから該当ファイルのタムスタンプを取得。(「ABSPATH」のパスの末尾には「/」が付与されているので注意。)
  3. 元々の出力用のパスに、取得したタイムスタンプをクエリとして付与してから返す。
function ag2add_file_ver($path){
  if(strpos($path, home_url()) !== false){
    //自動で付加されるwordpressバージョン情報のクエリを削除
    $path = preg_replace('/\?.+$/', '', $path);
    //サイトURL部分をサーバー内パスに置換
    $resource_path = str_replace(home_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のMozillaの公式ドキュメント

header('Cache-Control: no-store');

header(‘ヘッダー文字列’) : 生のHTTPヘッダーを送信する。

Cache-Control : HTTPのリクエストとレスポンスの両方でのキャッシュのためのディレクティブ(命令コマンド)。

no-store : レスポンスをキャッシュに保存することはできず、新しいリソースがキャッシュされることを防ぐ。(すでにキャッシュ済みの古いリソースが存在している場合、そのキャッシュの利用は防げない。)

 

 

この記事をシェア
この記事のURL

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>

コピー
※ フィールドをクリックでコピーするテキストの編集ができます。

この記事へのコメント

コメントの書き込みはまだありません。

  • コメント内のタグはエスケープ処理され、文字列として出力されます。
  • セキュリティーのため、投稿者のIPアドレスは取得されます。
  • 管理者が内容を不適切と判断したコメントは削除されます。
  • このフォームにはスパム対策として、Googleの提供するreCAPTCHAシステムが導入されています。
    (Google Privacy Policy and Terms of Service.)