この記事の目次
CSSの色を変えて保存したのに、公開ページは以前の色のまま。更新したCSSが反映されないとき、まず確かめたいのは「ブラウザーがどのURLから、どの内容を得たか」です。キャッシュを消して見た目が変わっただけでは、配信の仕組みまで直ったとは判断できません。
HTMLと外部CSSの読み込みが分かる人向けに、架空の写真室の見出しを使います。Node.js 24系と、Networkパネルを使えるブラウザーを用意してください。教材は端末内だけで動かし、実際のホスティング設定や公開中のサイトは変更しません。
調べる順番は、URL、本文、適用された値
最初に開発者ツールのNetworkを開き、ページを再読み込みします。CSSの通信を選び、HeadersのRequest URLとResponseの本文を見ます。Chrome DevToolsの公式資料で、それぞれの確認場所を調べられます。名称はブラウザーや表示言語で異なります。
| 観察した結果 | 次に調べる場所 |
|---|---|
| CSSのURLが予定と違う | HTMLのlink、公開先の階層、古いHTMLの配信 |
| URLは合うが本文に変更がない | 保存先、ビルド結果、配信先や途中のキャッシュ |
| 本文に変更があるが見た目が違う | 要素のクラス、適用条件、別のCSSによる上書き |
ファイル名だけでは、同名のCSSを別の階層から読んでいることを見落とします。URLはホスト名とパスまで照合します。相対パスの確認は最初の行、CSSの適用元を調べる記事は最後の行に進んだときに使えます。
応答本文には、今回変えた値を目印にします。今回ならh1のcolorが#174ea6かどうかです。状態コード200だけを合格条件にすると、「古いファイルを正常に受け取った」状態も通してしまいます。
304は、サーバーが変更なしと答えた結果
HTTPキャッシュは、受け取った応答を保存して再利用する仕組みです。保存分を再利用する前に、まだ同じ内容かを問い合わせる操作を再検証と呼びます。ETagはサーバーが内容の版を識別するために付ける値で、ブラウザーはIf-None-Matchで以前の値を送れます。
サーバーが同じ版と判断すれば304 Not Modifiedを返し、ブラウザーは保存済みの本文を使います。304自体に新しいCSS本文はありません。版が変わっていれば、今回の練習では200と新しい本文を返します。MDNのHTTPキャッシュの説明で、この往復を確認できます。
Cache-Control: no-cacheは、保存を禁止する名前ではありません。再利用前の検証を求める指定です。no-storeは保存をさせない指定で、両者は用途が違います。また、メモリーやディスクから再利用したという表示は、サーバーとの再検証で304を受けたこととは分けて記録します。
内容が変わればETagも変わる練習環境を作る
空の練習フォルダに、次の内容でstyle.cssを保存します。最初は濃い灰色です。
body { margin: 2rem; font-family: sans-serif; line-height: 1.8; }
h1 { color: #333333; }
同じフォルダへ次をserver.mjsとして保存します。CSSの本文から識別値を作り、同じ値が届いた場合だけ304を返す小さなサーバーです。公開用のサーバーではなく、再検証の条件を観察するための教材です。
import { createServer } from 'node:http';
import { readFile } from 'node:fs/promises';
import { createHash } from 'node:crypto';
const html = `<!doctype html><html lang="ja"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>写真室|キャッシュの練習</title>
<link rel="stylesheet" href="/style.css">
</head><body><h1>写真室の案内</h1>
<p>架空の練習ページです。見出しの色を変更します。</p>
</body></html>`;
createServer(async (request, response) => {
try {
if (request.url === '/') {
response.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8',
'Cache-Control': 'no-store'
});
response.end(html);
} else if (request.url === '/style.css') {
const css = await readFile(new URL('./style.css', import.meta.url));
const etag = '"' + createHash('sha256').update(css).digest('hex') + '"';
const unchanged = request.headers['if-none-match'] === etag;
response.writeHead(unchanged ? 304 : 200, {
'Content-Type': 'text/css; charset=utf-8',
'Cache-Control': 'no-cache',
ETag: etag
});
response.end(unchanged ? undefined : css);
} else {
response.writeHead(404, { 'Cache-Control': 'no-store' });
response.end('Not found');
}
} catch {
response.writeHead(500, { 'Cache-Control': 'no-store' });
response.end('Practice file could not be read');
}
}).listen(8766, '127.0.0.1', () => {
console.log('http://127.0.0.1:8766/');
});
ターミナルでnode server.mjsを実行し、表示されたローカルURLを開きます。終了はCtrl+Cです。ポートが使用中というエラーなら、別のアプリを勝手に止めず、末尾の8766を空いている番号へ変えます。HTTP応答を組み立てるAPIはNode.js 24の公式資料を参照できます。
この教材のETag照合は、一つの識別値がそのまま返る通常のブラウザー操作向けです。条件付きリクエストの全構文を実装したものではありません。依存ライブラリの導入や実運用の設定より、本文と版が対応することを観察します。
灰色、変更なし、青色の三つを記録する
NetworkのDisable cacheを外した状態で開き、style.cssのETagを控えます。続けて、ファイルを変更せず通常の再読み込みをします。標準的な再検証ではIf-None-Matchに控えた値が送られ、304が返ります。開発者ツールが再利用後の内容を見せる場合もあるので、本文欄が空かどうかだけで判断しません。
次にstyle.cssの#333333を#174ea6へ変えて保存し、再読み込みします。ETagが変わり、200の応答本文に#174ea6が入り、見出しも青くなれば対応が取れています。ブラウザーの操作や設定により条件なしで取り直した場合は200になります。304を出すためだけに設定を変え続けず、送った条件と結果を一組で読みます。
| 段階 | リクエストの条件 | 期待する応答と内容 |
|---|---|---|
| 初めて開く | 保存済みの識別値なし | 200、灰色のCSS、識別値A |
| 変更せず再検証 | If-None-MatchがA | 304、保存済みの灰色を利用 |
| 色を変更して再検証 | If-None-MatchがA | 200、青色のCSS、別の識別値B |
再読み込みを繰り返しても直らない二つの場面
一つ目は、キャッシュを疑っているのに実は違うCSSを編集している場合です。Disable cacheを有効にして取り直しても、応答本文に新しい色がありません。修正はRequest URLが指す配信物を特定し、その編集元を直して必要なビルドと配信をやり直すことです。再確認では、同じURLの本文に新しい値が入ったかを見ます。
二つ目は、青色のCSSが届いているのに、後から読んだ別の規則で灰色へ戻される場合です。再検証やキャッシュ削除を繰り返しても、CSS同士の優先関係は直りません。対象のh1を選び、計算済みのcolorから適用元へ戻って、その規則を修正します。本文が青、計算済みの値も青、という二段階で確認してください。
Disable cacheは、DevToolsを開いている間のブラウザーキャッシュを調べるために使います。CDNなど配信途中の保存内容を一括削除する機能ではありません。Service Workerが応答している表示がある場合も、通常のHTTPキャッシュだけの教材から外れるので、その配信経路を別に調べます。
本文の目印を変えて、原因の分岐を確かめる
15〜20分を目安に、青への変更を終えた後、見出しのfont-size: 28pxをCSSへ追加します。確認条件は、応答本文に28pxがある、ETagが前回から変わる、計算済みの文字サイズが28pxになる、の三つです。変更なしの再検証では、その版の保存内容を使えることも確認します。
URLを変える配信方式を採る場合も、HTMLが新しいURLを参照していなければ更新は届きません。まず今回の三条件でどこまで一致したかを記録し、恒久的なキャッシュ方針は配信環境に合わせて決めます。更新後の確認範囲の記事や公開・運用の無料レッスンの確認表には、「表示できた」に加えて、配信本文のどの値を見たかを残してください。
TRY A LESSON
記事の内容を、課題で確かめる
記載内容へのご質問や訂正のご連絡は、hello@junkbranding.comまでお願いします。