◉ANTIGRAVITY LABEN
記事一覧/アプリ開発
▣ アプリ開発/2026-10-15中級

immutable を付けた資産を同じ URL で差し替えたら、利用者のブラウザだけが古いままでした

長期キャッシュを付けた JS を同じ URL で差し替えても、CDN をパージしてもブラウザは取り直しません。同じ URL・no-cache・クエリ付き・内容ハッシュ名の 4 方式を Chromium で並べて比べ、ビルドの最後にハッシュを付ける完全なスクリプトまでをまとめました。

キャッシュCache-ControlCloudflare4ビルド個人開発105Antigravity382

✦ プレミアム記事

ビルドを終えて、同じ名前のまま JS を差し替えたときのことです。CDN 側で該当 URL をパージし、新しい版が配信されているはずなのに、手元のブラウザでは古い挙動が続いておりました。

パージは確かに効いていたのだと思います。効いていなかったのは、そのもう一段手前——利用者のブラウザの中でした。長期キャッシュを付けた資産を同じ URL で上書きするという、自分で決めた運用の裏側を踏んだのです。

最初にお伝えしたいのは結論です。同じ URL で中身を変えるなら、長期キャッシュは付けられません。長期キャッシュを付けるなら、中身が変わったら URL を変えます。 その線引きを 4 つの配信方式で並べ、手元の Chromium で確かめた結果と、ビルドの最後に置いているハッシュ付与のスクリプトを書き残します。

まず、層を切り分けます

「古いものが出る」と感じたとき、握っている層は三つ考えられます。CDN のエッジ、利用者のブラウザ、そして HTML が指している URL そのものです。パージが届くのはエッジだけで、ブラウザのキャッシュには何も届きません。

切り分けは、ブラウザの開発者コンソールで次の 2 行を打つだけで済みます。同じ URL を、キャッシュを使う設定と使わない設定で一度ずつ取ります。

// 何を解決するか: 古い版を握っているのがブラウザか、それより奥かを見分ける
const u = '/assets/app.js'; // 疑っている資産の URL に置き換えてください
const a = await (await fetch(u, { cache: 'default' })).text(); // ブラウザのキャッシュを使う
const b = await (await fetch(u, { cache: 'reload' })).text();  // 必ずサーバーまで取りに行く
console.log({ same: a === b, defaultHead: a.slice(0, 60), reloadHead: b.slice(0, 60) });
// なぜこう書くか: same が false なら、ブラウザが古い版を握っています。
// same が true で、それでも古いなら、握っているのはエッジかオリジンです(エッジの確認は別途 curl -I で)。

切り分けに使ったのは、この cache オプションの違いです。default では古い版、reload では新しい版が返ってきた時点で、原因は CDN ではなくブラウザ側だと決まります。パージを何度やり直しても無駄だったわけです。

4 つの配信方式を並べます

同じ資産を差し替えたとき、利用者に新しい版が届くかどうかを、方式ごとに見ていきます。

方式URLCache-Control差し替えの届き方
A 同じ URL・長期 + immutable/assets/app.jspublic, max-age=31536000, immutable届かない
B 同じ URL・長期のみ/assets/app.jspublic, max-age=31536000届かない
C 同じ URL・都度確認/assets/app.jsno-cache + ETag届く(毎回サーバーへ確認)
D クエリ付き/assets/app.js?v=2長期 + immutableHTML が新しければ届く
E 内容ハッシュ名/assets/app.3f9a1c2e.js長期 + immutableHTML が新しければ届く

表は設計上の期待値です。次の節で、これが実際のブラウザでどうなるかを確かめます。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦資産を差し替えたのに古い版が動くとき、CDN・ブラウザ・HTML のどの層が握っているかを fetch の cache オプション 2 回で切り分けられるようになります
✦同じ URL・no-cache・クエリ付き・内容ハッシュ名の 4 方式から、自分のサイトに合うものを手元の Chromium で確かめたうえで選べるようになります
✦リリースのたびに「パージしたのに直らない」を調べ直す時間を、ビルドの最後に 1 回走らせるハッシュ付与スクリプトで先に省けるようになります
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

▣ アプリ開発2026-09-29
Cloudflare をパージしても古い壁紙が届き続けた原因は、オリジン側で JPEG を握っていた XPageSpeed
同じ URL に上書きした壁紙画像が、Cloudflare をパージしても古いまま届き続けた運用の記録です。ローカル・オリジン・エッジの三者を突き合わせて層を名指しする検査、プレフィックスパージの使いどころ、Xserver の XPageSpeed を .htaccess で安全に切る書き方まで扱います。
▣ アプリ開発2026-09-19
見積書 PDF の自動化を一度にまとめて頼み、4 つに割り直すまで
受託の見積書を毎回コピーして作っていた手作業を、Antigravity に頼んで小さな PDF 出力ツールへ移した記録です。最初に全部をまとめて頼んで作り直すことになった理由と、データ・計算・見た目・保存の 4 つに割って渡し直した順番を、動くコードと一緒に書き残します。
▣ アプリ開発2026-05-21
Firebase Remote Config と Antigravity Agent で AdMob 配置を実運用しながら微調整する設計
壁紙アプリの AdMob 収益が頭打ちになった経験から、Firebase Remote Config と Antigravity Agent を組み合わせて広告配置を実運用中に少しずつ最適化する仕組みをまとめます。