プリキャッシング
参照元ページ: https://developers.google.com/web/tools/workbox/modules/workbox-precaching
プリキャッシュされた内容のレスポンスを返す
workbox.precaching.precacheAndRoute()
もしくはworkbox.precaching.addRoute()
はプリキャッシュされたファイルパス(URL)と一致するroute
を作成します。
このレスポンスのストラテジーはcache-first
と呼ばれます。cache-first
では、ネットワークからのレスポンスの代わりに、プリキャッシュされたコンテンツのレスポンスを返す仕様です(なんらかの不測の事態によりキャッシュからレスポンスが返せない時を除いて)。
workbox.precaching/precacheAndRoute()
もしくはworkbox.precaching.addRoute()
を呼ぶ順番は重要です。これらは通常、workbox.routing.registerRoute()
で追加のルーティングを登録する前にサービスワーカー内で呼ぶ必要があります。
プリキャッシュリストの説明
workbox-precaching
は文字列の配列かオブジェクトの配列を使います。例えば下記のように。
workbox.precaching.precacheAndRoute([
'/styles/example.ac29.css', //文字列
{
url: '/index.html'
revision: 'as46',
} //オブジェクト
])
workbox.precaching
に使われるリストは"リビジョニング"の情報と紐付けられた一式のURLを参照します。上記の例ですと、文字列で渡された/styles/example.ac29.css
のrevisionはURL自身となります。この方法により、すべてのブラウザで長期的にこれらのURLをキャッシュすることができます。このように各ファイルをリビジョニングすることで、プリキャッシュするファイルのリストを作ることができます。(補足: 文字列を渡す場合はファイル名を動的にハッシュ付きで生成することを想定しているようです)
URLにリビジョン情報(バージョン情報)を持たないファイルに対しては、1つのファイルの情報をオブジェクトにして、revision
プロパティを与える必要があります。これにより、いつファイルが更新されたかをworkbox-precaching
が知ることができます。
Workboxはこのリストを生成するツールを提供しています。
-
workbox-build
: npmモジュールでgulpやnpm scriptで使用できます -
workbox-webpack-plugin
: webpackユーザはこのプラグインを使えます -
workbox-cli
: これを使ってプリキャッシュリストを生成することも可能です
これらのツールを使うことで簡単にリストを作成することができますが、あなた自身で生成することも可能です。その場合は、ファイルの更新があるたびに、一意のrevision
プロパティを与えなくてはいけないことに注意してください。
// Revisioned files added via a glob
workbox.precaching.precache([
'/styles/example-1.abcd.css',
'/styles/example-2.1234.css',
'/scripts/example-1.abcd.js',
'/scripts/example-2.1234.js',
]);
// Precache entries from workbox-build or somewhere else
workbox.precaching.precache([
{
url: '/index.html',
revision: 'abcd',
}, {
url: '/about.html',
revision: '1234',
}
]);
// Add Precache Route
workbox.precaching.addRoute();
プリキャッシュファイルに対するリクエスト
workbox.precacheing
が行う素晴らしいことはネットワークへのリクエストを操作してプリキャッシュファイルのものと一致させることです。これはよくあるウェブのお作法を取り入れています。
例えば、/
に対するリクエストは/index.html
に置き換えてレスポンスが送られます。
下記にworkbox.precaching
が行う、操作の一覧を記載します。
URLパラメータを無視する
検索パラメータ付きのリクエストは特定の値もしくはすべての値を削除した形に置き換えられます。
デフォルトでは、utm_
の値は削除され、/?utm_=123
のようなリクエストは/
に変更されます。
ignoreUrlParametersMatching
に渡す値によって何のパラメータを削除したいか指定できます。
workbox.precaching.precacheAndRoute(
[
'/styles/index.0c9a31.css',
'/scripts/main.0d5770.js',
{ url: '/index.html', revision: '383676' },
],
{
ignoreUrlParametersMatching: [/.*/]
}
);
ディレクトリインデックス
/
で終わるリクエストは、末尾にindex.html
が付与されます。つまり/
でURLを指定した場合は/index.html
のキャッシュを見にいくことになります。
この挙動はdirectoryIndex
にnull
を渡すことで無効化できます。
workbox.precaching.precacheAndRoute(
[
'/styles/index.0c9a31.css',
'/scripts/main.0d5770.js',
{ url: '/index.html', revision: '383676' },
],
{
directoryIndex: null,
}
);
Clean URL
もしリクエストがプリキャッシュのものと一致せず失敗した場合は、"clean"(もしくは"pretty") URLsをサポートしており、末尾に.html
を付与します。これにより/about
のリクエストは/about.html
とマッチすることになります。cleanUrls
にfalse
を与えることで無効化できます。
workbox.precaching.precacheAndRoute(
[
'/styles/index.0c9a31.css',
'/scripts/main.0d5770.js',
{ url: '/index.html', revision: '383676' },
],
{
cleanUrls: false,
}
);
カスタムで操作する
飛んできたリクエストをカスタムで操作したい場合はurlManipulation
を使用できます。これはコールバックでマッチするオプションを渡すことできます。
workbox.precaching.precacheAndRoute(
[
'/styles/index.0c9a31.css',
'/scripts/main.0d5770.js',
{ url: '/index.html', revision: '383676' },
],
{
urlManipulation: ({url}) => {
...
return [alteredUrlOption1, alteredUrlOption2, ...];
}
}
);
上級者の使い方
PrecacheControllerを直接使う
デフォルトでは、workbox-precaching
はinstall
、activate
リスナーを設定してくれます。しかし、サービスワーカーに慣れ親しんだディベロッパーにとってはこの挙動は必ずしも望ましいとは限りません。
PrecacheController
を使用することでファイルのプリキャッシュのタイミングやキャッシュファイルの削除などを自由に決めることが可能です。
const precacheController = new workbox.precaching.PrecacheController();
precacheController.addToCacheList([
'/styles/example-1.abcd.css',
'/styles/example-2.1234.css',
'/scripts/example-1.abcd.js',
'/scripts/example-2.1234.js',
]);
precacheController.addToCacheList([
{
url: '/index.html',
revision: 'abcd',
}, {
url: '/about.html',
revision: '1234',
}
]);
self.addEventListener('install', (event) => {
event.waitUntil(precacheController.install());
});
self.addEventListener('activate', (event) => {
event.waitUntil(precacheController.cleanup());
});
self.addEventListener('fetch', (event) => {
event.respondWith(caches.match(event.request).then(...));
});