PWA: Workbox Precaching 和訳 (その２) 

# プリキャッシング

参照元ページ: 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`は文字列の配列かオブジェクトの配列を使います。例えば下記のように。

```js

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`プロパティを与えなくてはいけないことに注意してください。

```js

// 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`を使用することでファイルのプリキャッシュのタイミングやキャッシュファイルの削除などを自由に決めることが可能です。

```js

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(...));
});
```