• カミナリツイッターカミナリtwitter
  • カミナリフェイスブックカミナリfacebook
  • カミナリインスタグラムカミナリinstagram

山陰の情報を発信するカミナリ

ナビ

25

SEPTEMBER

ウェブTUESDAY 2018 / 9 / 25

cssやjavascriptファイルを参照する際にタイムスタンプを自動挿入する@WordPress

CSSやJavaScriptを修正した際、ブラウザ内にキャッシュが残っているためすぐに反映されない場合があります。

スーパーリロードをかければブラウザ内のキャッシュを使わずにリロードされて正常に反映されますが、ユーザー側に操作を求めるのはあまりスマートではないですよね。

 

システム側で対応できる方法として、ファイルを参照する際に

<link rel=”stylesheet” href=”http://example.com/style.css?timestamp=20180924 9:28:36“>

<script src=”http://example.com/script.js?timestamp=20180924 9:28:36“></script>

のように ? でGETパラメータを渡してファイルの更新日時(タイムスタンプ)を付与することで、ブラウザキャッシュを無効化することができます。

※ブラウザは style.css と style.css?1 を異なるファイルとして認識するため

 

 

そのへんの処理を自動的にやってみよう! というのが今回の趣旨です。

 

先に結論を書きますが、下記のコードを functions.php に記述しておくことで、wp_enqueue_style および wp_enqueue_script を使った際、自動的にタイムスタンプの付与処理が行なわれます。

また、後述していますがテンプレート内で手動で使いたい場合にも対応しています。

 

add_filter('style_loader_tag', 'add_timestamp_param_on_enqueue', 10, 3);
add_filter('script_loader_tag', 'add_timestamp_param_on_enqueue', 10, 3);

function add_timestamp_param_on_enqueue($html, $handle, $href){
  $varkey = 'timestamp';
  
  // ソースファイルのURLとサイトURLと先頭が一致しない場合は処理しない
  $siteUrl = site_url();
  if(strncmp($siteUrl, $href, strlen($siteUrl))===0){
    $isProc = true; // 処理するか否かのフラグ
    
    // $varkey の名前が別途指定されている場合は処理しない。
    $query = parse_url($href, PHP_URL_QUERY);
    if($query!==null){
      foreach(explode('&', $query) as $param){
        $a = explode('=', $param);
        if($a[0]===$varkey){
          $isProc = false;
          break;
        }
      }
    }
    
    // 処理する場合
    if($isProc){
      $docRoot = rtrim($_SERVER['DOCUMENT_ROOT'], '/').'/';
      $path = $docRoot . $uri;
      if(file_exists($path)){
        $newVar = filemtime($path);
        $symbol = $query===null ? '?' : '&';
        $newHref = $href.$symbol.$varkey.'='.$newVar;
        $html = str_replace($href, $newHref, $html);
      }
    }
  }
  
  return $html;
}
function the_timestamped_style($cssPath){
  echo add_timestamp_param_on_enqueue('<link rel="stylesheet" href="'.$cssPath.'">', 0, $cssPath);
}
function the_timestamped_script($jsPath){
  echo add_timestamp_param_on_enqueue('<script src="'.$jsPath.'"></script>', 0, $jsPath);
}

 

 

うまくいかない場合

パスは http等から始まる絶対パスで指定してください。

また、当然ながら外部サイトのファイルを参照している場合にはタイムスタンプは取得しません。
(厳密にはできなくもないですが、どうしても通信ラグが発生して遅延するので)

一般的な環境では問題なく使えるように作っていますが、mod_rewrite等を使って特殊なディレクトリ構成にしている場合にはローカルファイルを参照できず、タイムスタンプが付与できない場合があります。

 

テンプレート内に手動で組み込みたい場合

さっきのプログラム末尾に the_timestamped_style および the_timestamped_script という関数を追加しています。こちらをテンプレート内(header.php)で実行することでその箇所に挿入されます。

引数はファイルへのパス(絶対パス)のみで、タグの出力も行います。
以下使用例。

<?php the_timestamped_style(get_stylesheet_directory_uri().'/css/style.css'); ?>

 

ファイルへ付与するパラメータについて

実際に付与するパラメータは style.css?timestamp=1535617701 のようにUNIX時間を使うようにしています。

 

使っているフィルターフック

wp_enqueue_style の場合、link要素を出力する直前に style_loader_tag というフィルターフックを呼び出すため、そこで出力内容を書き換えることで対応しています。

wp_enqueue_script では script_loader_tag というフィルターフックがあり、そちらを使っています。

 

 

松本博之隠しプロフィール画像

TEXT by

松本 博之まつもとひろゆき)

1978年、鳥取県米子市生まれ。
株式会社マジックワード WEBシステムの開発・運用を担当。

WordPressの実績多数。表面的な使用方法を把握するだけでなく、WordPressのソースコードを読み解いて対応できます。
国家資格の基本情報処理技術者を保持。

この人が書いた他の記事を読む