49人がいいねしました

更新日

CSS・JSのキャッシュクリア|「変更されてないです」から解放されるCache Bustingを4つ紹介

web兄さん

Web制作で日常的に起こるトラブル事例

Webサイトを改修し本番環境にアップ。

クライアントからへ報告すると、変更できてない」とお叱りの連絡が来るケースがあります。

キャッシュは時として僕たちWeb制作者の敵となることがあるので、CSS・JS・画像ファイルのキャッシュを読み込ませない「Cache Busting(キャッシュバスティング)」の方法をWeb制作者向けにまとめました。

先にこの記事のまとめです。気になる箇所だけ読み進めてください。

  1. ブラウザキャッシュについての理解
  2. 【基本】手動でキャッシュを読み込ませないようにする方法
  3. PHPを使った場合👉filemtime()でファイルの更新日時を付与
  4. WordPressを使った場合👉filemtime()でファイルの更新日時を付与
  5. Gulpを使用している場合👉出力するhtmlの拡張子に乱数を追加する
  6. webpackを使用している場合👉[contenthash]をバンドルファイルに追加する

ブラウザキャッシュのおさらい

キャッシュの仕組み

ブラウザは高速でサイトを表示するために過去に開いたことのあるページのCSSやJS、画像といったファイルを保存して再利用しています。

これをブラウザキャッシュといいます。

それにより、保存された古いファイルが表示され変更されていないと勘違いしてしまうのです。

Q.キャッシュってどこに保存されるの?
A.ブラウザキャッシュといっても実際は端末に保存されています。そのためキャッシュが溜まりすぎるとPCの動作が遅くなります😓キャッシュデータが保存されている箇所がOSによって異なるので気になる方は調べてみてください。

開発者ツールからキャッシュを確認してみる

開発ツールでのキャッシュデータの確認

GoogleChromeの開発者ツールを使いNetwork>Sizeを確認すると、読み込んでいるリソース一覧と一緒に

  • リソースのサイズ(画像では22.6kB)
  • disk cache(or memory cache

が表示されます。このdisk cacheとなっているリソースがブラウザのキャッシュから読み込んでいるファイルとなります。


開発ツールでのキャッシュデータの確認

続けてDisable cacheにチェックを入れるとキャッシュを読み込ずにページをロードする設定に変更できます。

全てのリソースが読み込まれサイズが表示されていますよね。

web兄さん
逆にこの時点でキャッシュの原因かどうかを判断することもできますね!

ブラウザ側でできるキャッシュクリア2つ

こちらは本記事の趣旨とは少し異なりますが、weblikerは初学者向けのメディアなので、一応解説をしておきます。既にご存知の方は次のセクションへ読み飛ばしてください。

【方法1】シークレットブラウザで閲覧する

【方法1】シークレットブラウザで閲覧する

chromeのシークレットブラウザ

シークレットブラウザであればファイルをサーバーから読み込むためキャッシュファイルのない最新の状態で閲覧することができます。

OSショートカット
Maccommand + shift +N
Windowsctrl + shift + N

ITリテラシーの高いお客さんであれば

web兄さん
サーバーへアップしました。シークレットブラウザで確認ください!

というやりとりでも成り立つことには成り立ちますがリテラシーのあるお客さんばかりではありません。また、シークレットブラウザも開きっぱなしだとキャッシュは残るようです。

【方法2】ブラウザの設定からキャッシュをクリアする

【方法2】ブラウザの設定からキャッシュをクリアする【※非推奨】

ブラウザの設定からキャッシュをクリアする【※非推奨】

お客さんへ勧めるのはハードルが高い

ブラウザの設定からキャッシュクリアをすると全てのサイトのキャッシュが削除されてしまい、Cookieなども一緒に削除してしまった場合は、各種サービスのログインを再度しなければいけないなどデメリットも多いのでお客さんへ勧められません。


Cache Busting(キャッシュバスティング)によるキャッシュ回避

開発側でキャッシュされたCSSやJSを読み込ませず、更新されたファイルを読み込ませられたら一番楽ですよね。

その方法を専門用語でCache Busting(キャッシュバスティング)と呼びます。

web兄さん
キャッシュバスティングはCSSやJSのキャッシュをクリア(削除)するわけではなく、任意のファイルのみ改めて読み込ませることだと理解しておいてください。

パラメーターをつけることで新しいファイルが読み込まれる

まずは基本的なことを理解しておきましょう。ブラウザはファイルを読み込む際にパスを辿ってファイルを読み込みますよね?

そのため、パスに変化があると「キャッシュに無いファイルだ。読み込もう!」という動きをします。


以下のコードのファイル名の後ろに注目してみてください。

<!-- ローマ字でもOK -->
<img src="photo.jpg?renew">

<!-- 数字でもOK -->
<link rel="stylesheet" href="style.css?20220109">

<!-- 組み合わせてバージョン番号をつけてもOK -->
<script src="script.js?ver=1.2.1"></script>
/* 背景画像にもつけられます */
div{
  background-image: url(bg.jpg?20220720)
}

全てのファイル名の後ろに?〇〇という文字列がついていますよね。

この?〇〇という部分をパラメーターと呼びますが、ファイルにも任意でつけることができます。


とりあえず手動であれば上記のように対応することでCSSやJSのキャッシュを読み込ませることなく確実に更新ができますが、ちょっと面倒ですよね。

というわけで自動で対応させるための方法をいくつか解説していきます。

PHPでのキャッシュ回避

ファイルの更新日時(タイムスタンプ)を取得するfilemtime('filepath')を使用します。

<?php $cachebusting = date('YmdHis', filemtime('style.css')); ?>
<link rel="stylesheet" href="style.css?<?php echo $cachebusting; ?>">

filemtime()タイムスタンプが更新されるタイミング

  • ファイル作成時
  • ファイルの内容の変更時
  • 保存実行時

ただこの方法はPHPで開発する場合なので使用頻度は高くないかもしれません。

WordPress環境でのキャッシュ回避

WordPressの場合は関数からの読み込みが一般的なのでwp_enqueue_style()の第四引数に対して、

date('Ymd', filemtime('filepath'))を記述します。

// アセットパス
define('ASSETS_DIR', get_template_directory_uri().'/assets');
define('ASSETS_PATH', get_template_directory().'/assets');

// CSS
$style_path = '/css/style.css';

wp_enqueue_style(
  'main', //ハンドル
  ASSETS_DIR.$style_path, //パス
  array(), //依存関係
  date('YmdHis',filemtime(ASSETS_PATH.$style_path)) //パラメーター
);

// JS
$js_path = '/js/script.js';

wp_enqueue_script(
  'main', //ハンドル
  ASSETS_DIR.$js_path, //パス
  array(), //依存関係
  date('YmdHis',filemtime(ASSETS_PATH.$js_path)) //パラメーター
);

Gulpでのキャッシュ回避

Gulpの場合はタイムスタンプではなく乱数を生成してキャッシュ回避をします。

少し古い記事ですがこちらの記事を参考にさせていただきました。最小限のコードではありますがやりたいことはできたのでこちらの方法を紹介します。


最低限必要なものは以下の2つです。それぞれインストール

npm install --save crypto
npm install --save-dev gulp-replace

6行目で乱数を生成しています。

24行目、25行目で出力するhtmlファイルの.css.jsいう文字列をパラメーター付きの文字列に置換しています。imgも同じ要領で対応可能です。

const gulp = require('gulp');
const sass = require('gulp-dart-sass');
const replace = require('gulp-replace');
const crypto = require('crypto');

const hash = crypto.randomBytes(6).toString('hex'); //16進数の乱数を生成

/**
 *  Sass
 */
const scss = () => {
  return gulp.src('src/scss/**/*.scss', {
    sourcemaps: true
  })
    .pipe(sass({ outputStyle: 'expanded' }))
    .pipe(gulp.dest('dist/css/', { sourcemaps: './' }))
}

/**
 *  HTML
 */
const html = () => {
  return gulp.src('src/index.html')
    .pipe(replace('.css','.css?'+hash))
    .pipe(replace('.js','.js?'+hash))
    .pipe(gulp.dest('dist'))
}

/**
 *  WATCH
 */
const watchfile = () => {
  gulp.watch('src/scss/**/*.scss', gulp.series(scss)),
  gulp.watch('src/index.html', gulp.series(html))
}

/**
 *  デフォルト
 */
exports.default = gulp.series(
  gulp.parallel(html,scss),
  gulp.parallel(watchfile)
);

とりわけ難しいことはしていないので、ご自身の環境に追加しやすいと思います。

出力されると以下のような形で出力されます。

<link rel="stylesheet" href="./css/style.css?f9ae1bf88a03">
<script src="./js/script.js?f9ae1bf88a03">

webpackでのキャッシュ回避

ポイントとなる箇所だけ書いています。

webpackの場合標準で備わっている[contenthash]を追加するだけでバンドルされたファイルにハッシュ値を追加することができます。

The [contenthash] substitution will add a unique hash based on the content of an asset. When the asset’s content changes, [contenthash] will change as well.

https://webpack.js.org/guides/caching/

バンドルされるJSとCSSにそれぞれ以下のように記述することで対象となるファイルが変更されるたびにハッシュ値を更新します。

output: {
    filename: `./${dir.assets}/js/[name].[contenthash].js`,
    path: path.resolve(__dirname, 'dist'),
}
plugins: [
  new MiniCssExtractPlugin({
    filename: "[name].[contenthash].css",
  }),
]

このような形で出力されます。

<script defer src="main.ad63cc6359d5a6dcfa21.js"></script>
<link href="style.css?08fbf53aba5b1e2b4429" rel="stylesheet">

スクール越えの圧倒的なコスパ1ヶ月でWeb制作を身に着ける

プロのメンターサポート付き実務レベルのコーディングカリキュラム

詳細を今すぐチェック!

ギャクサンで作成するポートフォリオサイトのイメージ

記事では見れない豆知識

圧倒的なコスパを体感1ヶ月でWeb制作を身に着ける

プロのメンターサポート付き実務レベルのコーディングカリキュラム

詳細を今すぐチェック!

ギャクサンで作成するポートフォリオサイトのイメージ