49人がいいねしました
更新日
CSS・JSのキャッシュクリア|「変更されてないです」から解放されるCache Bustingを4つ紹介
Webサイトを改修し本番環境にアップ。
クライアントからへ報告すると、「変更できてない」とお叱りの連絡が来るケースがあります。
キャッシュは時として僕たちWeb制作者の敵となることがあるので、CSS・JS・画像ファイルのキャッシュを読み込ませない「Cache Busting(キャッシュバスティング)」の方法をWeb制作者向けにまとめました。
先にこの記事のまとめです。気になる箇所だけ読み進めてください。
- ブラウザキャッシュについての理解
- 【基本】手動でキャッシュを読み込ませないようにする方法
- PHPを使った場合👉
filemtime()
でファイルの更新日時を付与 - WordPressを使った場合👉
filemtime()
でファイルの更新日時を付与 - Gulpを使用している場合👉出力する
html
の拡張子に乱数を追加する - webpackを使用している場合👉
[contenthash]
をバンドルファイルに追加する
ブラウザキャッシュのおさらい
ブラウザは高速でサイトを表示するために過去に開いたことのあるページのCSSやJS、画像といったファイルを保存して再利用しています。
これをブラウザキャッシュといいます。
それにより、保存された古いファイルが表示され変更されていないと勘違いしてしまうのです。
- Q.キャッシュってどこに保存されるの?
- A.ブラウザキャッシュといっても実際は端末に保存されています。そのためキャッシュが溜まりすぎるとPCの動作が遅くなります😓キャッシュデータが保存されている箇所がOSによって異なるので気になる方は調べてみてください。
開発者ツールからキャッシュを確認してみる
GoogleChromeの開発者ツールを使いNetwork
>Size
を確認すると、読み込んでいるリソース一覧と一緒に
- リソースのサイズ(画像では22.6kB)
- disk cache(or memory cache)
が表示されます。このdisk cache
となっているリソースがブラウザのキャッシュから読み込んでいるファイルとなります。
続けてDisable cache
にチェックを入れるとキャッシュを読み込ずにページをロードする設定に変更できます。
全てのリソースが読み込まれサイズが表示されていますよね。
ブラウザ側でできるキャッシュクリア2つ
こちらは本記事の趣旨とは少し異なりますが、weblikerは初学者向けのメディアなので、一応解説をしておきます。既にご存知の方は次のセクションへ読み飛ばしてください。
【方法1】シークレットブラウザで閲覧する
【方法1】シークレットブラウザで閲覧する
シークレットブラウザであればファイルをサーバーから読み込むためキャッシュファイルのない最新の状態で閲覧することができます。
OS | ショートカット |
---|---|
Mac | command + shift +N |
Windows | ctrl + shift + N |
ITリテラシーの高いお客さんであれば
というやりとりでも成り立つことには成り立ちますがリテラシーのあるお客さんばかりではありません。また、シークレットブラウザも開きっぱなしだとキャッシュは残るようです。
【方法2】ブラウザの設定からキャッシュをクリアする
【方法2】ブラウザの設定からキャッシュをクリアする【※非推奨】
ブラウザの設定からキャッシュをクリアする【※非推奨】
- GoogleChromeでのキャッシュクリア
- Safariでのキャッシュクリア:「Safari」>「履歴を消去」
- firefoxでのキャッシュクリア
- iPhone/iPadでのキャッシュクリア
お客さんへ勧めるのはハードルが高い
ブラウザの設定からキャッシュクリアをすると全てのサイトのキャッシュが削除されてしまい、Cookieなども一緒に削除してしまった場合は、各種サービスのログインを再度しなければいけないなどデメリットも多いのでお客さんへ勧められません。
Cache Busting(キャッシュバスティング)によるキャッシュ回避
開発側でキャッシュされたCSSやJSを読み込ませず、更新されたファイルを読み込ませられたら一番楽ですよね。
その方法を専門用語でCache Busting(キャッシュバスティング)と呼びます。
パラメーターをつけることで新しいファイルが読み込まれる
まずは基本的なことを理解しておきましょう。ブラウザはファイルを読み込む際にパスを辿ってファイルを読み込みますよね?
そのため、パスに変化があると「キャッシュに無いファイルだ。読み込もう!」という動きをします。
以下のコードのファイル名の後ろに注目してみてください。
<!-- ローマ字でも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">