Webデザイン

WordPressのWebサイト更新時にキャッシュを自動で削除する方法

強力すぎるブラウザキャッシュを自動で削除

どうもこんにちは。
Web/App/UIデザイナーのサトウです。

今回は、WordPressのWebサイト更新時にキャッシュを自動で削除する方法について書いていきます。

Webサイトの更新業務時、ブラウザ(特にモバイル向けSafariやChrome)の強力すぎるキャッシュに悩まされているあなたは是非読んでみてください。

「変わってないです」をなくしたい

クライアントからの依頼でWebサイトの文言や画像を変更し、クライアントにテスト環境を確認してもらうと、

クライアント
クライアント
変わってないです。

といった連絡をいただくことがあります。
そのたびに

サトウ
サトウ
ブラウザのキャッシュが表示されているものと思われます。
キャッシュをクリアして再度ご確認いただけますでしょうか。

というもはや定型文といっても過言ではない回答にキャッシュクリアの方法を添えて返信するという一連の流れ。
Webサイトの運用・更新業務に携わっているデザイナー、コーダー、エンジニアであれば、この経験は一度や二度ではないでしょう。

そもそも、更新業務の確認のたびにキャッシュ削除の操作をしてもらうのもクライアントに対してちょっと申し訳ないですよね。
また、モバイル向けのSafariやChromeといったブラウザはキャッシュが強力すぎてなかなか削除できず、わざわざプライベートモードで確認してもらわなければならないケースもあり厄介です。
無駄な工数が発生してしまっているという意味でも解決すべき事案です。

さらに、更新の確認時のみならず、実際のユーザーの中にもキャッシュで古い情報を閲覧してしまう一般ユーザーがいる可能性もあります。
これは非常によろしくない。

モバイル向けSafari, Chromeの強力すぎるキャッシュ

先日も、あるWebサイトの更新業務でクライアントに確認をお願いした際、こんなやり取りが発生しました。

クライアント
クライアント
履歴やキャッシュ削除したり、プライベートブラウズで見たりして、どうにかsafariだと普通に表示されましたが、chromeだと未だ改善されず、、
一発とは言わないですが、サクッと表示される方法とかはありますか?
サトウ
サトウ
んー、、、キャッシュはブラウザ側でクリアするしかないですが。。。モバイルのChrome、キャッシュクリアしてもダメですか?
クライアント
クライアント
モバイルのChrome、キャッシュクリア、履歴も全期間クリアとかしてみましたがだめでした。
シークレットモードは見れました。

このクライアントはすでにお付き合いも長く、変更内容がキャッシュで更新されないことがあるというのはよく理解してくださっているクライアントなので、キャッシュの削除についてはお伝えしなくても実施してくださいますが、それでも更新されず困ってしまいました。

こうなるとこちらとしてもさすがにどうにかしないわけにはいきません。

【CSS編】Webサイト側でブラウザのキャッシュを強制削除する

この方法は、正しくは「キャッシュを削除する」わけではなく、「キャッシュを読まずに新しいファイルを読むようにする」という方法です。

「文字色が変わってないです」「画像が大きく(小さく)表示されてます」等、CSSのキャッシュに起因するトラブルともこれでおさらばです。

CSSの呼び出しファイル名に任意の文字列(バージョンナンバー等)を付ける

CSSの呼び出しファイル名の末尾に文字列(バージョンナンバー等)を付けることで、「CSS変わってるよ」ということをブラウザに明示するというものになります。
こんな感じで。。。↓

<link rel="stylesheet" href="<?php bloginfo('template_directory') ?>/style.css?20220731210800">

上記の例では、年月日時分秒を付与しています。
試してみると、確かにちゃんと更新されて、変更した内容が反映されました。

なるほど! 賢い!
こちらの記事↓を参考にさせていただきました。

この方法は静的な記述を手動で変更するというものなので、WordPressを利用したWebサイトではない静的に作られたWebサイトでも実施可能です。

ただ、これだとCSSに何かしらの変更を施したあと、いちいち呼び出し側ファイルにも変更を加えなくてはならず、かなり面倒です。
これを自動でやることができたら最高じゃないですか。

functions.phpに細工をしてCSSの呼び出しファイル名に任意の文字列(バージョンナンバー等)を自動で付ける

ここからは WordPress を前提とした話になります。
静的な HTML + CSS のサイトの場合は、前述の手動バージョンで対応することになります。
もしかするとそういうのを自動でやってくれるエディターがあったり、開発環境の設定次第でデプロイ時に自動で付与とかあるかもしれないですが、ちょっとわからないです。
興味があれば調べてみてください。

さて、ではいきましょう。
functions.phpにコードを追加して、「CSSファイルの更新日時を取得し、呼び出し側のファイル名に自動で付与する」という方法です。
つまり、前述の方法を完全自動化する方法ということになります。
最高ですね。

functions.php にこのような形↓で記述すると、

function my_update_styles( $styles ) {
  $mtime = filemtime( get_stylesheet_directory() . '/style.css' );
  $styles->default_version = $mtime;
}
add_action( 'wp_default_styles', 'my_update_styles' );

header.php にこのような形↓で出力されます(<php wp_head(); ?>により出力)。

<link rel="stylesheet" href="テーマディレクトリ/style.css?ver=220730133717">

こちらの記事↓を参考にさせていただきました。

style.css の更新日時を php の filemtime 関数で取得し、$mtime という変数に代入。
その $mtime を $styles->default_version に指定して、wp_default_styles のアクションフックを使って出力する、ということですね。
もちろん ‘/style.css’ の部分は実際の環境に合わせて適宜変更です。

ところが、試してみたところ残念ながら成功しませんでした。
まったく同じコードや似たようなコードを紹介している記事がいくつもあったので、おそらくポピュラーな方法なんだと思うんですが、僕の場合はこの方法を試してもCSSの呼び出しファイル名に更新日時は付与されませんでした。

不思議に思いいくつかのサイトで試してみたところ、ちゃんと更新日時が付与されるケースとされないケースがありました。

なぜCSSの呼び出しファイル名に更新日時が付与されなかったのか?

header.php に直接外部CSSの呼び出しを記述していると、その箇所には更新日時が付与されないことがわかりました。
この方法は、functions.php で wp_enqueue_style 関数によって呼び出されているCSSに対して有効になるものなんですね。

なので、この方法でCSSにバージョンを付与しようとするなら、CSSの読み込み方法を、header.phpへの直接記述ではなく、functions.phpで設定しておく必要があります。

CSSを更新したらwp_enqueue_styleでキャッシュをクリアする

ということで、wp_enqueue_style関数について理解しておこうと調べていると、さらに別の方法を発見しました。
functions.phpへのwp_enqueue_style関数記述でCSSを読み込みつつ、更新日時の取得とファイル名への付与を同時におこなえる記述方法です。
素晴らしい。

こちら↓のwp_enqueue_style関数を使います。
ちなみに「enqueue」は「エンキュー」と読みます。

<?php wp_enqueue_style( $handle, $src, $deps, $ver, $media ); ?>

今回対応したいWebサイトでは、テーマディレクトリの中にcssディレクトリがあり、その中に格納されている複数のcssファイルを読み込みたいのと、一部のページでは専用のpageテンプレートを使用していて、cssも専用のものを読み込みたいので、このような記述↓になりました。

wp_enqueue_style( 'style', get_template_directory_uri() . '/css/style.css', array(), date("ymdHis", filemtime( get_stylesheet_directory().'/css/style.css')) );
wp_enqueue_style( 'style2', get_template_directory_uri() . '/css/style2.css', array('style'), date("ymdHis", filemtime( get_stylesheet_directory().'/css/style2.css')) );
if (is_page_template('page_lp.php')) {
	wp_enqueue_style( 'style_lp', get_template_directory_uri() . '/css/style_lp.css', array(), date("ymdHis", filemtime( get_stylesheet_directory().'/css/style_lp.css')) );
}

第一引数 $handle

第一引数でそれぞれのスタイルシートを識別するための名前を指定します。

第二引数 $src

第二引数ではスタイルシートのファイルパスを指定します。
基本的にはテーマディレクトリに格納されていると思うので、 get_template_directory_uri() か get_stylesheet_directory() を適宜使って記述します。

第三引数 $deps

第三引数には複数のCSSを使う場合の依存関係を指定します。
今回の僕のケースでは、style.css が元々あったCSSで、運用上僕が追加した style2.css があり、style2.css で style.css に書かれた既存の class を上書きしてたりもするので、style2 の第三引数には style を指定しておきました。
これにより、style.css を読み込んだあとに style2.css を読み込みます。
依存関係が不要の場合は、空欄ではなく「array()」と記述します。

第四引数 $ver

第四引数が今回の肝ですね。
filemtime関数でCSSの更新日時を取得し、date関数でフォーマットを指定して代入しています。

第五引数 $media

第五引数はデフォルトの「all」でいいので空にしています。
指定する場合は「screen」や「print」等、適宜指定します。

そうして出力されたのがこちら↓。

<link rel='stylesheet' id='style-css'  href='テーマディレクトリ/css/style.css?ver=220712082800' media='all' />
<link rel='stylesheet' id='style2-css'  href='テーマディレクトリ/css/style2.css?ver=220730133530' media='all' />
<link rel='stylesheet' id='style_lp-css'  href='テーマディレクトリ/css/style_lp.css?ver=220730133717' media='all' />

素晴らしい。最高です。
ランダムにいくつかの箇所を変更して様子を見ましたが、キャッシュが表示されてしまうことなく、更新した内容が即時反映されていました。
もちろん、モバイル版の Safari や Chrome でもしっかり更新されていましたよ!
気持ちいい。。。

こちらの記事↓を参考にさせていただきました。

【画像編】Webサイト側でブラウザのキャッシュを強制削除する

画像についても、CSS同様ファイル名末尾にバージョンナンバーを付与してファイル変更を明示する方法でキャッシュを回避できます。
つまり、imgタグの画像ファイル名に対して

<img src="テーマディレクトリ/img/banner.png?ver=220731164325">

といったような形で更新日時をバージョンとして付与するということです。

もちろん、手動で ?ver=220731164325 等の文字列を書き足してもいいですが、なるべく余計な手間は省きたい。
とはいえ。。。
画像はCSSとはちょっと勝手が違います。

  • CSSは対象となるファイルを指定したが、画像の場合は画像ディレクトリの中に格納しているすべての画像が対象。
  • CSSは <?php wp_head(); ?> によって出力されるが、画像はテーマファイル/投稿/固定ページに静的に記述されている。

なかなか難易度が高そうですね。。。
ちょっと探してみた感じだと、この要望を満たすような施策を紹介している記事は見つかりませんでした。

ページを表示しようとしたときに、ページ内のimgタグを洗い出して、該当する画像ファイルを見にいって更新日時を取得し、imgタグのファイル名末尾に文字列として追加して、ページを出力する。

という処理を、ページを表示するたびにしなければいけないというのはかなりヘビーな気がします。
画像の多いページならなおさらです。

理想的なのは、ページを表示しようとしたときに処理するのではなく、画像を更新したときに、その画像が使われているページの該当箇所のファイル名に更新日時がバージョンナンバーとして付くという感じですが、やはり難易度が高そうです。

imgタグのファイル名に任意の文字列(バージョンナンバー等)を手動で付ける

ひとまず、自動で処理することを諦め、「imgタグのファイル名に任意の文字列(バージョンナンバー等)を付ける」という処理を手動でおこなうことにします。
「画像を同一ファイル名で差し替えず別ファイル名で更新する」という方法よりはマシでしょう。。。

今回の方法はWordPressのサイトじゃなくてもできる

今回の、ファイル名末尾に文字列を付与する方法自体は、WordPressのサイトじゃなくても、どんなサイトでも使用可能な方法です。
静的に記述する分にはどんなサイトでも利用できますし、動的に出力する場合でもプログラミングの知識のある人ならいかようにも対応できるはずです。

画像の最適化プラグインを使っている場合は要注意

WordPressで画像の最適化プラグインを使っている場合は注意が必要です。

アップロードした画像を圧縮したりWebpに変換してそれを表示してくれるようなプラグインを使っている場合、元の画像を差し替えても最適化画像が差し替えられないことがあります。

そういったプラグインを使用している場合は、画像を差し替えたら忘れずに再度最適化の処理をおこないましょう。

さて、今回は、WordPressのWebサイト更新時にキャッシュを自動で削除する方法について書いてみました。
いかがだったでしょうか?
読んでくださったあなたの参考に少しでもなれば嬉しいです。
それではまた次回。