tl;dr
- Nuxt.js向けのPWAモジュール(pwa-module)が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
の一部です。
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
)で検証してみます。
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を見ると、このコミットでpreCacheに関する修正が入っていました。
preCacheの指定方法
ドキュメントを見ると、オフライン対応に関わるプロパティがあります。
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でキャッシュストレージに格納されます。
workbox.routing.registerRoute(new RegExp('/_nuxt/'), new workbox.strategies.CacheFirst ({}), 'GET')
まとめ
デフォルトの挙動から推測すると、すべてのバンドルファイルをむやみにpreCacheしないようにし、読み込んだページで使うjsファイルを順次キャッシュしていく。そして、本当にpreCacheしたい静的アセット(static
配下にあるもの)は個別に指定するという意図がうかがえます。
すべてのバンドルファイルをむやみにpreCacheしない
に関しては、アプリケーションの画面数が増えるに従って、ある1つの画面で最初に読み込んだときのオーバーヘッドが大きくなってしまうので、結果として理解できるものだと思います。
ただ、Service Workerで実行される処理はメインスレッドではないのでパフォーマンス面においてはおそらく影響はないかと思います。
一度も表示していないページはオフラインで表示されなくなってしまいますが、AppShellに該当する部分はOKでも結局動的に取得するコンテンツが表示されないので、一気に全ページをpreCacheするメリットもそこまで大きくないものといえます。
よってv3での変更は、v2のときよりも合理的・実践的にキャッシュするようになったように思います。