先日、電子コミックの続刊を通知するサイトを作ったのですが、けっこうゴリゴリとjavascriptを書きました。
修正してはchromeで確認をして・・・を繰り返していたのですが、chromeを開発者モードにするのを忘れて「あれ?修正したのに動いてない?」と戸惑うことが多々あり。chromeはキャッシュの機能が優れていて、以前読み込んだjsやcssは再読み込みしないんですね。
これ、サイトを公開してから何度も来てくれる人も同じ問題起きちゃうなぁ・・・と気が付いたので、対応することにしました。
Cache Busting を使おう
HTML の meta タグで “no-cache” を指定すれば毎回キャッシュをせずに読み込むようになりますが、読み込むのはファイルを更新したときだけにしたいので、もうちょっと良いものはないかと探したところ、見つけました。
https://qiita.com/yaju/items/d0ff9771de4cd854654d
.jsファイルを呼び出すときに、ファイルの後ろにGET形式(xxx.js?key=val)でパラメータを付ければ良いらしい。Cache Busting というらしいです。名前かっこいいな!
こうすれば、キャッシュをさせたいタイミングでパラメータを変更すればURLが変わったとブラウザが認識するので、再読み込みされるわけですね。なるほど~。
さらに上記のサイトではファイルの更新日時を使っていて、「ファイルを更新したときだけ再読み込みさせたい」の目的にぴったりだったので、使うことにしました。
PHP では filetime() を使って Cache Busting する
.jsと.cssを更新したときだけ再読み込みさせるサンプル作ってみました。
<?php
define(DIR_ROOT,"/home/~のようなディレクトリパス",true);
?>
<!DOCTYPE html>
<html>
<meta charset="utf-8" />
<head>
<link href="/css/style.css?v=<?php echo filemtime(DIR_ROOT."/css/style.css");?>" rel="stylesheet" />
</head>
<body>
<script src="/js/sample.js?v=<?php echo filemtime(DIR_ROOT."/js/sample.js");?>"></script>
<body>
</html>
これを実行すると、.jsや.cssのパスの後ろに「/js/sample.js?v=1513072511」のように日時の値が入ります。他のサイトのサンプルでは、dateで日付の形式(20171213~)にフォーマットしていたのですが、この文字列自体にあまり意味はないのでfiletimeの素の値でも良いかと思います。
ファイルが存在しないとphp自体がエラーになってしまうので、絶対にエラーを出しちゃいけないサイトではfiletime()の前にファイルの存在確認ロジックを入れたほうが良いかもしれません。
Prism.js の読み込みにも Cache Busting させてみる
この記事を書いて途中 Prism.jsにphpを入れていないことに気づき、急いでphpを追加した.jsファイルに差し替えたところ・・・読み込まれない。まさにこの記事の最初の問題が起こってしまいました。
Prism.jsの読み込みは WordPressのテーマのfunctions.phpに任せているので、そこを修正してみました。
3-4行目でprism.jsと.cssの読み込みに filetime() と get_stylesheet_directory() を使ってCache Bustingさせています。
//参考:https://odd-one-out.serek.eu/prism-wordpress-without-plugin/
function add_prism() {
wp_register_style('prismCSS', get_stylesheet_directory_uri() . '/css/prism.css?v='.filemtime(get_stylesheet_directory().'/css/prism.css'));
wp_register_script('prismJS', get_stylesheet_directory_uri() . '/js/prism.js?v='.filemtime(get_stylesheet_directory().'/js/prism.js'));
global $post, $wp_query;
$post_contents = '';
if ( is_singular() ) {
$post_contents = $post->post_content;
} elseif ( is_archive() || (is_front_page() && is_home())) {
$post_ids = wp_list_pluck( $wp_query->posts, 'ID' );
foreach ( $post_ids as $post_id ) {
$post_contents .= get_post_field( 'post_content', $post_id );
}
}
if ( strpos( $post_contents, '<code class="language-' ) !== false ) {
wp_enqueue_style('prismCSS');
wp_enqueue_script('prismJS');
}
}
add_action('wp_enqueue_scripts', 'add_prism');
安心安心。