WordPressでCSS更新が反映されない|キャッシュ5層の切り分けとfilemtimeで二度と揉めない運用

CSS
この記事は約11分で読めます。

WordPressでCSSを更新したのにクライアントの画面に反映されない——犯人はキャッシュです。ただし「どのキャッシュか」を特定しないと対処できません。この記事では、実案件で踏んだ切り分け手順と、filemtimeによるキャッシュバスティングで二度と揉めない運用を解説します。

ある日、サイト更新を納品した午後にクライアントから「変更されてないです」と連絡が来ました。自分のPCでもスマホでも新しいデザインがちゃんと表示されているのに、先方には古いまま見えている。

結論から言うと、犯人はキャッシュでした。しかも「ブラウザキャッシュだけ」ではなく、WP Fastest CacheのページキャッシュにSimple Custom CSS and JSのインライン出力が巻き込まれて起きた、よくあるのに見落としやすい事故でした。

キャッシュは「層」になっている

キャッシュは5つの層で積み重なっています。「キャッシュが原因」と分かっても、どの層かを特定しないと対処できません。

1. ブラウザキャッシュ——CSS・JS・画像などをユーザーの端末がローカルに保存するもの。一度読み込んだファイルを再利用して表示を高速化します。

2. WordPressプラグインのページキャッシュ——WP Fastest CacheやW3 Total Cacheが、動的に生成されるページを静的HTMLとして保存するもの。

3. minified CSS/JS——キャッシュプラグインが複数のCSS/JSを結合・圧縮して生成する別ファイル。元のCSSを更新しても、この結合後ファイルが残っていれば古いCSSが配信されます。

4. CDNキャッシュ——CloudflareなどのCDNエッジサーバーに保存されたファイル。

5. Service Worker(PWA等)——PWAを導入している場合の独自キャッシュ層。他のすべてを削除しても古いコンテンツが表示されることがあります。

DevToolsで(from disk cache)が表示されている画面

今回の僕の構成は、WP Fastest Cache(無料版)+ functions.phpのwp_enqueue_style() + Simple Custom CSS and JS(SilkyPress製)。この組み合わせで、2層目と3層目が複雑に絡んで反映トラブルが起きていました。

切り分け:まず「同じ景色」を見る

「自分には見えている、相手には見えていない」という状況では、いきなり原因を推測せず、再現から始めるのが最短ルートです。

シークレットウィンドウで開く

ブラウザのシークレットモードは既存のキャッシュやCookieを使わずにページを読み込みます。ここで新しいデザインが見えれば、自分の通常ブラウザにキャッシュが残っている可能性が高い。見えなければサーバー側のキャッシュが原因です。

別端末・別回線で見る

シークレットでも変わらない場合は、スマホのモバイル回線や別のPCなど、まったく別の環境で確認します。「自分だけ見えている」という食い違いをほどくには環境を変えるのが一番早い。

DevToolsのNetworkタブで確認する

CSSのURLクエリパラメータ確認画面

ChromeのDevTools(F12)→ Networkタブでページをリロードし、2つのポイントをチェックします。

CSSやJSに「(from disk cache)」が付いていないか。これが付いていれば、ブラウザはサーバーにリクエストを送らず古いファイルを使っています。

CSSファイルのURLが更新前後で同じままになっていないか。たとえば/assets/css/style.css?ver=1.0.0のverが変わっていなければ、ブラウザは「同じファイルだから再取得不要」と判断してキャッシュを使います。

Empty Cache and Hard Reload メニュー

Empty Cache and Hard Reload

DevToolsを開いた状態でリロードボタンを長押しすると「Empty Cache and Hard Reload」が出ます。これでキャッシュを全削除した上で全ファイルを再取得できます。ここで先方も新しいデザインが見えるなら「端末側のキャッシュ」、見えないなら「サーバー側のキャッシュ」と確定できます。

今回の犯人:カスタムCSSが「HTMLに埋まっていた」

Simple Custom CSS and JSがインライン出力になっていたため、CSSがHTMLの一部としてページキャッシュに含まれ、CSSだけ更新してもページキャッシュが残る限り永遠に古いCSSが表示され続けていました。

切り分けを進めると、先方の画面でもCSSファイル自体は読み込まれているように見える。でもCSSが効いていない。URLを確認すると自分と先方で同じ。

ここで犯人が絞られました。Simple Custom CSS and JSの設定を確認したところ、カスタムCSSが「インライン出力」になっていたのです。

CSSは外部ファイルではなくページHTMLの一部。WP Fastest Cacheがそのページを静的HTMLとしてキャッシュすると、インラインCSSもキャッシュの中に含まれる。Simple Custom CSS and JSでCSSを更新しても、ページキャッシュが残っている限り古いCSSが返される。これが「更新したのに反映されない」の正体でした。

応急処置:クライアントへの案内テンプレート

原因がキャッシュだと判明した時点で、すぐにクライアントへ案内してください。この返しが早いほど不信感を防げます。

以下はそのまま使える文面です。

お世話になっております。

こちらの環境では更新が正常に確認できており、端末側に旧データがキャッシュとして残っている可能性が高いです。

お手数ですが、以下をお試しいただけますでしょうか。

【PCの場合(Chrome)】
サイトを開いた状態でF12 → 開発者ツールが開いた状態でリロードボタンを長押し →「Empty Cache and Hard Reload」を選択

【スマホの場合】
別のブラウザで開く/Wi-Fiを切ってモバイル回線で開く

こちらでもサーバー側のキャッシュ削除を実施いたします。

ポイントは「端末側に旧データが残っている可能性」という表現で相手のせいにしないこと、「こちらも対応する」姿勢を見せることの2つです。

根本解決:二度と起きないキャッシュバスティング運用

filemtime()でバージョンを自動更新し、Simple Custom CSS and JSは外部ファイル出力にし、キャッシュ削除はminifyファイルも含めて実行する。この3つで「更新が反映されない」は仕組みとして潰せます。

1. functions.php:filemtimeでバージョン自動更新

wp_enqueue_style()の第4引数にファイルの更新日時を渡します。ファイルを更新するたびにタイムスタンプが変わるのでURLも自動的に変わり、ブラウザは新しいファイルとして取得します。

出力されるURLはこうなります。

手動でver=1.0.1 → ver=1.0.2と上げていく運用は、だいたい忘れます。filemtime()なら更新のたびに自動で変わるので、人間が忘れても大丈夫です。file_exists()でチェックしているのは、子テーマ構成などでファイルパスが変わった場合に警告を出さないようにするためです。

2. Simple Custom CSS and JS:外部ファイル出力にする

Simple Custom CSS and JSの設定画面

今回の直接原因がインライン出力だったので、外部ファイル出力を基本にします。

WordPress管理画面の「カスタムCSS & JS」→ 対象のコードを編集 →「Options」→「Linking type」を「External File」に変更して保存。

外部ファイルなら、CSSは独立したファイルとして読み込まれるため、ファイル単位でキャッシュが管理されます。インラインのようにページキャッシュに巻き込まれません。

もしインライン出力が必要な事情(クリティカルCSSの埋め込みなど)がある場合は、「カスタムCSS/JSを更新したら必ずページキャッシュを削除する」をルール化してください。

3. WP Fastest Cache:minifyファイルも含めて削除する

WP Fastest Cacheの削除画面

WP Fastest Cacheには「ページキャッシュ」と「minified CSS/JS」の2種類があります。CSS更新時はこの両方を削除する必要があります。

WordPress管理画面 →「WP Fastest Cache」→「Delete Cache」タブで、「Delete Cache」(ページキャッシュ)と「Delete Cache and Minified CSS/JS」(結合・圧縮ファイル)の両方を実行。

「CSSを変えたのに反映されない」のうち、ページキャッシュよりもminify生成物が古いまま残っているせいで起きるケースが体感では多いです。

画像が変わらないときの対策

画像はCSS/JS以上にキャッシュが残りやすい。「同名上書き」を避けてファイル名を変えるのが最も確実です。

画像のmax-ageは長めに設定されていることが多く、hero.jpgを新しい画像で上書きしても古い画像が表示され続けます。

推奨:ファイル名を変える。hero.jpg → hero-20260115.jpgのように日付やバージョンをファイル名に含めれば、確実に別ファイルとして認識されます。

代替:クエリパラメータを付ける。<img src="hero.jpg?v=20260115">で対応できますが、一部のCDNやプロキシはクエリパラメータを無視することがあるので、ファイル名変更の方が確実です。

他のキャッシュプラグインの場合

プラグインが違っても「ページキャッシュ + minifyキャッシュの両方を削除する」という考え方は同じです。

W3 Total Cache:Performance → Page Cache → empty cache / Performance → Minify → empty cache

WP Super Cache:設定 → WP Super Cache → キャッシュを削除(minify機能なし、ページキャッシュのみでOK)

LiteSpeed Cache:LiteSpeed Cache → ツールボックス → すべてをパージ / CSSキャッシュをパージ / JSキャッシュをパージ

Autoptimize(併用時):設定 → Autoptimize → キャッシュを削除。キャッシュプラグインと併用している場合は両方のキャッシュを削除する必要があります。

再発防止チェックリスト

更新前のルールと更新後の手順を明文化しておけば、キャッシュ問題は仕組みとして潰せます。

更新前(制作時のルール)

  • CSS/JSはwp_enqueue_style()/wp_enqueue_script()で読み込む
  • バージョンはfilemtime()で自動更新
  • Simple Custom CSS and JSは外部ファイル出力を基本にする
  • 画像の差し替えは「同名上書き」を避け、ファイル名を変更する

更新後(納品時の手順)

  • WP Fastest Cacheでページキャッシュ + minifyファイルの両方を削除
  • シークレットウィンドウで更新を確認
  • 別回線(モバイル回線など)で確認
  • CDN使用時はCDNキャッシュもパージ
  • クライアントへ強制再読み込み手順を案内

トラブル発生時

  1. シークレットウィンドウで開く → 変化あれば端末キャッシュ
  2. 別端末・別回線で確認 → 変化あればネットワークキャッシュ
  3. DevToolsのNetworkタブで「from cache」を確認
  4. Empty Cache and Hard Reloadで確認
  5. 上記すべてダメならサーバー側キャッシュを疑う

僕はこのチェックリストを保守契約の手順書に追記しました。これだけで、納品直後の不毛なやり取りが激減しています。

まとめ

「直したのに直ってないと言われる」は、キャッシュの層構造を理解して仕組みで潰せば二度と起きません。

キャッシュは5層(ブラウザ・プラグイン・minify・CDN・Service Worker)あり、切り分けはシークレットウィンドウ→別端末→DevToolsの順で進めます。根本対策はfilemtime()でバージョン自動更新、Simple Custom CSS and JSは外部ファイル出力、キャッシュ削除はminifyファイルも含めて実行。これを納品手順として明文化しておけば、クライアントとの信頼関係を損なう事故は防げます。

コメント

タイトルとURLをコピーしました