📑

プログラマ泣かせのブラウザキャシュ

2023/07/17に公開

直したはずのCSSが当たっていない

CSSの修正って結構面倒ですよね。もちろん最近はCSSを直接編集せずSASSの技術を使うことが多いと思います。それでも、細かい数字を調整するのは苦労します。
それでやっとできたと思って、確認すると何も変わっていない。これほどガックリすることはありません。
SASSのコンパイルがうまくいってないのか?CSSファイルを直接エディタで確認しても、ちゃんとコンパイルされています。
実際、これで1時間ぐらい悩むのことは何度かありました。

そんな時は強制リロード

まず、試してもらいたのがこの強制リロードです。それってなにかというと、修正したCSSファイルやJSファイルを強制的に再読み込みすることです。

このブログをご覧になっている方々にとっては当然のこととは思いますが、あえて説明しておくとブラウザは常に画面に表示すべき内容(専門的な表現だとレンダリングすべきDOM要素)を常に全てサーバーから読み込んでいるわけではありません。DOM要素以外のCSSファイルやJSファイル、イメージファイルなども同様で、一度読み込んだデータはキャッシュと呼ばれるメモリに保存され、変化がないと判断するとそれを使いまわすのです。これは重要な機能でパフォーマンスの維持には欠かせません。この機能があるから画面がサクサク切り替わるのです。

しかし、これがCSSやJSを修正したのに直っていないという原因になるのです。ですから、Web制作に携わる方々はそのことを常に念頭に置いて、クライアント様にはそのことを伝えないといけません。

「そんなのリロードすれば勝手にやってくれてんじゃないの?」「再起動すればさすがに再読み込みするんでしょ。」なんて思われがちでしょうが、そうはいきません。下記の操作以外では、強制リロードと同じ効果は得られません。

でも、実際には強制リロードって難しい

キーボード操作で簡単に実行できる強制リロードですが、一般ユーザーはその方法をほぼ知らないでしょう。そのため、これを素人のクライアント様に伝えるのはかなり困難です。

また、パソコンは上記の方法で簡単に操作できますが、スマホの場合はそんなキー操作ができません。かなり面倒な操作が必要で、私などなんどやっても覚えられません。この方法を説明しだすとそれだけで一記事になるので、ここではしません。参考となるURLを張っておきますのでそちらをご覧ください。

スーパーリロードのやり方は?スマホやiPhoneとブラウザ別で紹介

ということで結論です

ご存じのとおり、ブラウザは次のようなコードでcssファイルやjsファイルを読み込んでいます。

link rel="stylesheet" href="./css/example.css

先ほどブラウザは、「前に読み込んだファイルに変化がないと判断するとそれを使いまわす」と説明しましたが、このようにファイル名が固定されているとファイル名が変わらない限り、過去に読み込んだファイルと判断してしまうのです。
ですが、逆にいうとファイル名が変われば再度読み込みを行います。つまり、再読み込みの際にファイル名が変わっていればよいということです。その方法は以下のとおりです。

link rel="stylesheet" href="./css/example.css?<?php echo date('YmdHis')

つまり、ファイル名のあとに?'.date('YmdHis')というスクリプトをつけてファイル名をかえるというわけです。date('YmdHis')は時間を返すPHPの関数です。したがって、このスクリプトはブラウザに読み込んだ時間付のファイル名を渡すことになり、違うファイル名になるため、過去に読み込んだことがあるという判断はできないことになります。これで常に新しいCSSが読み込まれるという仕組みが出来上がります。
しかし、この方法はPHPのスクリプトが機能することが前提なので、静的なHTMLファイルでは実現できません。また、どんなファイルにも、この設定をしてしまうとキャッシュ機能が失われるのでmp4の動画ファイルのような大容量のファイルに、この手法を適用するのはまずいと思います。そんなファイルについては、やはり強制リロードによるしかないと考えます。
CSSやJSはいくら長いといっても1MBに達することはないでしょう。また、これらのファイルはバージョンアップの度に変わるもので、不特定多数のユーザーが利用するプラグインなどでは強制リロードの説明は困難ですから、利用価値は非常に高いと思います。
ということで最後にWordpressサイトでよく使われるスクリプトの書き方を紹介します。テーマならfunction.phpに、プラグインならエントリポイントとなるPHPファイルに埋め込んで使用してみてください。

function my_script_init()
{
  wp_enqueue_style('my', get_template_directory_uri() . '/css/style.css?'.date('YmdHis'), array(), '1.0.0', 'all');
}
add_action('wp_enqueue_scripts', 'my_script_init');

Discussion