ブラウザのキャッシュ活用とファイル名にMD5フィンガープリント追加方法 – WordPress高速化2(後編)

今回は前回の記事『ブラウザのキャッシュ活用とファイル名にMD5フィンガープリント追加方法 – WordPress高速化2(前編)』の続き(後編)となります。前編では、ブラウザのキャッシュクリア対策として、MD5のファイル名付与対応を主にGruntを使って行う方法を説明しました。けっこう大変だったりしたので、今回はもっと楽に行う方法を書きたいと思います。

前編の続きとなります。いきなりこのページに来た方は、まずは前編をお読みください。

こんなやり方も – PHP側でHTMLを書き換える

Gruntでやると

ブラウザのキャッシュクリア対策のために「ファイル名にMD5フィンガープリントを付与すること」をGoogleが推奨していました。

これをタスクランナーであるGruntで行うと以下のような複数のタスクを実行する必要があり、設定など行うのにそれなりの労力を必要としました。

  • ファイルの更新の監視(grunt-contrib-watch)
  • 古いファイルの削除(grunt-contrib-clean)
  • ファイル名にMD5を付与したファイル生成(grunt-md5)
  • 生成したファイルのファイル名取得(Node.jsのfsモジュール)
  • HTML側の書き換え(grunt-text-replace)

PHPでファイル名を取得する処理を書く

「ファイル名にMD5を付与したファイル生成」はGruntにやらせるとして、HTML側の書き換えをPHPでやらせてもよいのではないかと思い試したやり方を紹介したいと思います。

まずGruntでも同じよう処理を行いましたが、対象のファイルのあるディレクトリにアクセスして、ファイル一覧を取得し、正規表現でファイル名を取得するクラスを作ります。

<?php
class Get_file_name {

  private $dir;
  private $pattern;
  public $match_word;

  // コンストラクター
  // (「ディレクトリパス」と「ファイル名の正規表現パターン」を引数に取る)
  function __construct($d, $p) {
    $this->dir = $d;
    $this->pattern = $p;
  }

  // ファイル一覧を取得するためのメソッド定義
  private function get_file() {

    // ディレクトリが存在し、ディレクトリにアクセスできた場合
    if (is_dir($this->dir) && $dh = opendir($this->dir)) {

      // ファイル一覧を取得し、ファイルが存在する場合はループ処理
      while (($file = readdir($dh)) !== false) {

        // check_fileメソッドを実行し、trueだった場合は処理終了
        if ($this->check_file($file) === true) {
          break;
        }

      }

      // ディレクトリへのアクセス終了
      closedir($dh);

    }

  }

  // ファイル名を正規表現から取得するためのメソッド定義
  private function check_file($f) {

    // ファイル($f)に対してパターンマッチングして、
    // 結果を$matches配列に格納
    preg_match($this->pattern, $f, $matches);

      // $matches[1]がtrueだったら、$match_word変数に格納
      if (isset($matches[1])) {
        $this->match_word = $matches[1];
        return true;
      }

    }

    // initメソッドを定義
    public function init() {
      $this->get_file();
      return $this->match_word;
    }

}
get_file_name.php

WordPressのfunction.phpで読み込み、処理実行

上記のファイルを適当な場所において、WordPressのfunction.phpで読み込み、処理を実行させるようにします。

// 処理を書いたファイルを読み込む
require("get_file_name.php");

// cssのファイル名を取得するインスタンス生成
$css_file =  new Get_file_name("/wp-content/themes/blog/assets/", "/^(app\-[0-9a-z]{32}\.css)$/");
// jsのファイル名を取得するインスタンス生成
$js_file = new Get_file_name("/wp-content/themes/blog/assets/", "/^(app\-[0-9a-z]{32}\.js)$/");
function.php

HTML側の変更

HTML側でcssファイルとjsファイルを読み込んでいる部分を以下のように変更します。

<!-- cssファイルを読み込んでいる箇所 initメソッドを実行 -->
<link rel="stylesheet" href="/wp-content/themes/blog/assets/<?php $css_file->init(); ?>">

<!-- jsファイルを読み込んでいる場所 initメソッドを実行 -->
<script src="/wp-content/themes/blog/assets/<?php $js_file->init(); ?>"></script>
header.phpやfooter.phpなど

これで、assetsディレクトリにMD5を付与したファイルを置くと、HTML側で自動的にファイルを読み込んでくれるようになります。ただし、PHPの処理に更新日時の新しいファイルを読み込むといった処理を入れいていないので、古いファイルは手動で削除する必要があります

おまけ – query string(クエリ文字列)を使う

ブラウザのキャッシュをクリアするための他の方法としてquery string(クエリ文字列)を使う方法があったりします。こちらの場合、ファイル名を変更する必要がなく、HTML側のソースにクエリ文字列を挿入するだけで済みます

query string(クエリ文字列)を付与した例

  • /wp-content/themes/blog/css/app.css?ver=20150222003015
  • /wp-content/themes/blog/js/app.js?ver=20150222003015

ただし、注意が必要でURLに「?」が含まれていると、proxyにキャッシュされなくなってしまうようです。

そういった理由で、Googleもフィンガープリントを付与することを推奨しているんだと思いますが、念のため「おまけ」として対応方法を書いておきます。

Gruntでクエリ文字列を付与する

こちらについてはGruntで簡単に設定できます。前編で紹介したファイル内のテキストを書き換えるGruntプラグイン「grunt-text-replace」を使います。詳細は「前編」をご確認ください。

Gruntfile.jsの書き方は以下の通りです。
Gruntのテンプレート関数「grunt.template.today」を使ってファイルの更新した日時を取得して(<%= grunt.template.today('yyyymmddhhmmss') %>を挿入)、動的にを書き換えるようにしています。

module.exports = function (grunt) {

  var pkg = grunt.file.readJSON('package.json');

  grunt.initConfig({

    // replaceタスクを定義
    replace: {

      // cssターゲットを定義
      css: {
        src: ['header.php'], // 対象となるファイルのパス
        overwrite: true, // マッチしたソースファイルを上書きする場合は「true」
        replacements: [{
          // 置換前の文字列(ファイルのパス[正規表現で])
          from: /\/wp-content\/themes\/blog\/css\/app\.css\?ver\=[0-9]{14}/g,
          // 置換させる文字列
          to: "/wp-content/themes/blog/css/app.css?ver=<%= grunt.template.today('yyyymmddhhmmss') %>"
        }]
      },

      // jsターゲットを定義
      js: {
        src: ['footer.php'], // 対象となるファイルのパス
        overwrite: true, // マッチしたソースファイルを上書きする場合は「true」
        replacements: [{
          // 置換前の文字列(ファイルのパス[正規表現で])
          from: /\/wp-content\/themes\/blog\/js\/app\.js\?ver\=[0-9]{14}/g,
      // 置換させる文字列
          to: '/wp-content/themes/blog/js/app.js?ver=<%= grunt.template.today("yyyymmddhhmmss") %>'
        }]
      }

    },

    // watchタスクを定義
    watch: {

      // cssターゲットを定義
      css: {
        // 監視したいファイル
        files: 'css/app.css',
        // 変更を感知した時に実行するタスク
        tasks: 'replace:css'
      },

      // jsターゲットを定義
      js: {
        // 監視したいファイル
        files: 'js/app.js',
        // 変更を感知した時に実行するタスク
        tasks: 'replace:js'
      }

    }

  });

  // 使用するgruntプラグインを読み込む
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-text-replace');

};

HTML側は最初だけ置換できるように、query string(クエリー文字列)をつけた状態に書き換えておきます。

<!-- cssファイルの読み込み部分(header.php)-->
<link rel="stylesheet" href="/wp-content/themes/blog/css/app.css?ver=20150211090239">

<!-- jsファイルの読み込み部分(footer.php)-->
<script src="/wp-content/themes/blog/js/app.js?ver=20150211090204"></script>
HTMLテンプレート側(css、jsファイルを読み込んでいる箇所)

これでquery stringを使って、ブラウザのキャッシュをクリアさせることができるようになります。

いろいろやった挙句…

最後に、いろいろ説明してきましたが、実はWordPressの「autoptimize」というプラグインを使うと、何も考えずに圧縮、結合のみならず最適化はMD5のファイル名付与までやってくれます

コメント一覧

  • 必須

コメント