【Nuxt.js】pwa-module v3におけるpreCacheの仕様変更

## tl;dr
- [Nuxt.js向けのPWAモジュール（pwa-module）](https://pwa.nuxtjs.org/)がv3ベータになったタイミングでpreCacheのデフォルトの挙動が変わった
- v2までは、NuxtのバンドルファイルがService WorkerのpreCache対象になっていたが、デフォルトで入らなくなった
- preCacheするファイルは自身で指定する必要がある
- 基本的には`static`配下の静的アセットを指定することになる
- Nuxtのバンドルファイルはページ表示時に使用しているもののみruntimeCacheされる


## v2までのpreCacheの挙動
pwa-moduleを有効化すると、Service Workerのスクリプト（`sw.js`）が自動生成されるようになります。
v2まではNuxtのバンドルファイルがpreCacheされるように`sw.js`内に追加されていました。
下記は`v2.6.0`を導入して出力された`sw.js`の一部です。

```javascript:sw.js
importScripts('/_nuxt/workbox.4c4f5ca6.js')

workbox.precaching.precacheAndRoute([
  {
    "url": "/_nuxt/00b59f91ebc09a152054.js",
    "revision": "b1411b6485ed07411c9cf4c8eda659ac"
  },
  {
    "url": "/_nuxt/00c89fe340f7690c1b47.js",
    "revision": "103c1052066c72fea62c0d1fcecbc843"
  },
  {
    "url": "/_nuxt/139b3f511bb228368d2f.js",
    "revision": "7f95ecf2041623471d4ecd7ed0352605"
  },
], {
  "cacheId": "my-pwa",
  "directoryIndex": "/",
  "cleanUrls": false
})

workbox.clientsClaim()
workbox.skipWaiting()

workbox.routing.registerRoute(new RegExp('/_nuxt/.*'), workbox.strategies.cacheFirst({}), 'GET')
workbox.routing.registerRoute(new RegExp('/.*'), workbox.strategies.networkFirst({}), 'GET')

```

`workbox.precaching.precacheAndRoute`の部分に、Nuxtのバンドルファイルが全てのJSファイルが羅列されるようになっていました。
各preCache対象にはリビジョン番号が付与され、ブラウザのCache Storageに保存されます。
アプリケーションをバージョンアップした場合など、Service Workerが新しくなった場合は、`sw.js`から参照するリビジョンが変わるため、新しいjsファイルがpreCacheされます。

## v3でのpreCacheの挙動
v3にバージョンアップした際にどうなるか見てみましょう。執筆時点ではの最新バージョン（`3.0.0-beta.16`）で検証してみます。

```javascript:sw.js
importScripts('https://cdn.jsdelivr.net/npm/workbox-cdn@4.3.1/workbox/workbox-sw.js')

// --------------------------------------------------
// Configure
// --------------------------------------------------

// Set workbox config
workbox.setConfig({
  "debug": false
})

// Start controlling any existing clients as soon as it activates
workbox.core.clientsClaim()

// Skip over the SW waiting lifecycle stage
workbox.core.skipWaiting()

workbox.precaching.cleanupOutdatedCaches()

// --------------------------------------------------
// Precaches
// --------------------------------------------------

// Precache assets

// --------------------------------------------------
// Runtime Caching
// --------------------------------------------------

// Register route handlers for runtimeCaching
workbox.routing.registerRoute(new RegExp('/_nuxt/'), new workbox.strategies.CacheFirst ({}), 'GET')
workbox.routing.registerRoute(new RegExp('/'), new workbox.strategies.NetworkFirst ({}), 'GET')
```

### v3での変更点
一目瞭然ですが、Nuxtのバンドルファイルが自動的にpreCache対象に追加されなくなりました。
Releaseを見ると、[このコミット](https://github.com/nuxt-community/pwa-module/commit/67f1c3d)でpreCacheに関する修正が入っていました。


### preCacheの指定方法
[ドキュメント](https://pwa.nuxtjs.org/modules/workbox.html#options)を見ると、オフライン対応に関わるプロパティがあります。

#### offlineAssets
> (Array) List of assets to precache, in case you need extra files precached other than on the fly caching (_nuxt/* etc) or you want to ensure assets used by your offlinePage. (Example: ['/offline.png'])

配列でpreCacheする対象を指定します。
ここでバンドルファイルをワイルドカードで指定してみたりもしましたが、Service WorkerのpreCacheはパスの完全一致でキャッシュするようでした。Nuxtのバンドルファイルはビルド時にランダムな数字がファイル名に付与されうので、この段階でバンドルファイルを追加されるようにするのは無理そうです。

この仕様から意図を推測するに、`static`配下の静的アセットだけ追加するのが推奨されている感じがしました。

### Nuxtバンドルファイルのキャッシュ
#### assetsURLPattern
> (String/Regex) Pattern to match assets for runtime caching.
> Default is auto generated based on publicPath. Supports CDN too.
> Default: /_nuxt/

`assetsURLPattern`というプロパティの説明を見ると、`publicPath`に基づいてruntimeCacheされることがわかります。
故に、バンドルファイルはデフォルトでruntimeCacheでキャッシュストレージに格納されます。

```javascript:sw.js
workbox.routing.registerRoute(new RegExp('/_nuxt/'), new workbox.strategies.CacheFirst ({}), 'GET')
```

## まとめ
デフォルトの挙動から推測すると、すべてのバンドルファイルをむやみにpreCacheしないようにし、読み込んだページで使うjsファイルを順次キャッシュしていく。そして、本当にpreCacheしたい静的アセット（`static`配下にあるもの）は個別に指定するという意図がうかがえます。

> すべてのバンドルファイルをむやみにpreCacheしない

に関しては、アプリケーションの画面数が増えるに従って、ある1つの画面で最初に読み込んだときのオーバーヘッドが大きくなってしまうので、結果として理解できるものだと思います。
ただ、Service Workerで実行される処理はメインスレッドではないのでパフォーマンス面においてはおそらく影響はないかと思います。
一度も表示していないページはオフラインで表示されなくなってしまいますが、AppShellに該当する部分はOKでも結局動的に取得するコンテンツが表示されないので、一気に全ページをpreCacheするメリットもそこまで大きくないものといえます。

よってv3での変更は、v2のときよりも合理的・実践的にキャッシュするようになったように思います。