
【Next】PWA対応後videoが裏で読み込み続けられる問題
2022/11/01
Nextでnext-pwaによるPWA化を行った後、裏側でvideoのsrcがすべて読み込み続けられる問題が発生しました。

上記画像赤枠のようにvideoタグのpreload属性をmetadataにしていても表示段階からすべての動画が読み込まれるので、対策していないとネットワークリソースが大きく消費される可能性があります。
リファレンスも少なく対応に少し手間どったので、今後同じ問題に直面した方向けに概要を記録しておきます。
原因
最初のリクエスト画像をよくみると左側に歯車アイコンがあるリクエストとそうでないリクエストがあります。
歯車アイコンがないリクエストは通常のリクエストで、videoタグのpreload属性がmetadataなので、動画長などのmetadataのみをとってきています。
一方で歯車アイコンがあるリクエストはServiceWorkerからのリクエストを意味しており、videoタグのpreload="metadata"に関わらず全データを取得しています。
これはNextのPWA化に伴い、ServiceWorkerがファイルをフロントにcacheしようとするために起こる現象です。
すなわち、オフラインでもmp4などの動画を見れるように、ServiceWorkerが動画のcacheを試みてくれてるわけです。
画像などの軽いファイルではありがたい機能ですが、動画ファイルとなるとGB単位のものあるのでページを開いただけで全データを取得しようとするのは避けたいところです。
また、ServiceWorker自体はページに依存せず裏で動き続けるものなので、ページを切り替えたとしても動画の読み込みは終わらないことも厄介な点です 😱
動画を複数載せている画面とかだと、一気にダウンロードされる可能性もあるので対策しておきましょう(あえて取得させている場合は除く)。
対応
next-pwaはデフォルトで色々なものをcacheしようとするので、mp4などをcacheしないようにcache strategyを変更します。
next-pwaによるPWA対応後のnext.config.jsは例えば以下のようになっていると思われますが、
const withPWA = require('next-pwa')({
dest: 'public',
// runtimeCaching: [...], ← これ
//...
})
module.exports = withPWA({
// next.js config
})cache strategyの変更はこの中のruntimeCachingを弄ることで可能です。
runtimeCachingの詳細に関してですが、next-pwa自体は内部でworkbox-webpack-pluginを使用しており、runtimeCachingオプションに関してもこれと同様のものが設定可能です。
next-pwaがデフォルトで使用しているcache strategyはnext-pwaリポジトリにまとまっています。
mp4のみをcache strategyから省きたい場合は、上記リンク先のcache strategyをruntimeCachingへコピペして以下のようにmp4部分を変更します。
const withPWA = require('next-pwa')({
dest: 'public',
runtimeCaching: [
...
// {
// urlPattern: /\.(?:mp4)$/i,
// handler: 'CacheFirst',
// options: {
// rangeRequests: true,
// cacheName: 'static-video-assets',
// expiration: {
// maxEntries: 32,
// maxAgeSeconds: 24 * 60 * 60 // 24 hours
// }
// }
// },
// ↓ 以下のように変更
{
urlPattern: /\.(?:mp4)$/i,
handler: 'NetworkOnly',
},
...
],
})
module.exports = withPWA({
// next.js config
})
ここではhandlerをNetworkOnlyとすることで拡張子がmp4のファイルに対してcacheを行わないようにしました。
CacheFirstやNetworkOnlyなどはworkbox特有のstrategy名であり、詳細はこちらにまとまめられています。
mp4だけではなく、その他もcacheから外したい場合は適宜handlerを変更してください。
おわり
ここらへんのドキュメント少ない...
