Service Worker Cache Problems

822a7ca9bc8e5fb40911b82bcc9f39d5?s=47 biga816
April 17, 2019

Service Worker Cache Problems

822a7ca9bc8e5fb40911b82bcc9f39d5?s=128

biga816

April 17, 2019
Tweet

Transcript

  1. Service WorkerのCacheで ⾊々と問題が起きた話 Akihiro Tanaka(@biga816)

  2. とりあえずService Workerで キャッシュしまくってみた

  3. 前提 ɾ地下アイドル向けのDAppsをPWAしてみたときの話。 ɾionic3を利⽤。 ɾSW-Toolboxを利⽤(今はDeprecatedとなっている)。

  4. 問題1 キャッシュの上限に到達!

  5. 問題1 〜キャッシュの上限に到達〜 ɾ画像をキャッシュするようにしたら下記エラーが発⽣。 ɾファイルをキャッシュしすぎたためキャッシュ可能容量の上限 に達していた。 self.toolbox.router.get(/<ファイルサーバーのURL>/, (request) => { return

    new Promise((resolve, reject) => { caches.match(request).then((response) => { if (response) { // from cache resolve(response); } // from network return fetch(request) .then((response) => resolve(response)) .catch((error) => reject(error)); }); }); });
  6. 解決策 ɾキャッシュ数の上限と期限を設定した。 self.toolbox.options.cache = { name: 'ionic-cache', maxAgeSeconds: 60 *

    60 * 24, maxEntries: 50 };
  7. 問題2 開発環境でのみキャッシュの上限に到達!

  8. 問題2 〜開発環境でのみキャッシュの上限に到達〜 ɾ下記のエラーが気がついたらまた発⽣するようになった。 ɾ開発環境ではAoTコンパイルが実⾏されていないため、キャッ シュ対象となっていたアプリ⾃体のjsがキャッシュ容量を圧迫 していた。 self.toolbox.precache( [ './build/main.js', './build/vendor.js',

    './build/main.css', './build/polyfills.js', 'index.html', 'manifest.json' ] ); AoTコンパイル なしだとデカい
  9. 問題2 〜開発環境でのみキャッシュの上限に到達〜 ɾキャシュの上限はブラウザによって異なる。 <参考> https://developers.google.com/web/fundamentals/instant-and-offline/web-storage/offline-for-pwa

  10. 解決策 ɾ定期的にキャッシュを削除した。 ɾローカルで開発する際にはServiceWorkerをオフにしても良 かったかも。

  11. 問題3 キャッシュから動画が再⽣されない!

  12. 問題3 〜キャッシュから動画が再⽣されない〜 ɾSafariでのみ問題が発⽣。 ɾサーバーからデータを取得する初回は動画が再⽣されるが、2 回⽬以降キャッシュから取得する際には動画が再⽣されない。 Client App Cache Server

  13. 問題3 〜キャッシュから動画が再⽣されない〜 サーバーからの場合のHTTPヘッダ キャッシュの場合のHTTPヘッダ ɾHTTP Rangeリクエストに対し、Safariではレスポンスコード 200を受け取るとそれ以降そのファイルを読み込まない仕様に なっていた

  14. 解決策 ɾRangeリクエストが来た際にステータスコード206で返却する ようにService Workerでレスポンスを上書きする。

  15. self.toolbox.router.get(/<ファイルサーバーのURL>/, (request) => { return new Promise((resolve, reject) => {

    if (request.headers.get('range')) { // Range request let rangeHeader = request.headers.get('range'); let rangeMatch = rangeHeader.match(/^bytes¥=(¥d+)¥-(¥d+)?/) let pos = Number(rangeMatch[1]); let pos2 = rangeMatch[2]; if (pos2) { pos2 = Number(pos2); } caches.open('ionic-cache') .then((cache) => { return cache.match(request.url); }).then((res) => { if (!res) { return fetch(request.url).then(res => res.arrayBuffer()); } else { return res.arrayBuffer(); } }).then((ab) => { let responseHeaders = { status: 206, statusText: 'Partial Content', headers: [ ['Content-Type', 'video/mp4'], ['Content-Range', 'bytes ' + pos + '-' + (pos2 || (ab.byteLength - 1)) + '/' + ab.byteLength]] }; : Qiita: Service Worker(PWA)でRangeリクエストに対応する https://qiita.com/biga816/items/dcc69a265235f1c3f7e0 抜粋
  16. まとめ ɾService Workerのキャッシュは便利だけど上限を意識する必要 がある。 ɾ無限に増えるコンテンツはCDNでキャッシュした⽅が良い。 ɾキャシュ対象はオフラインで最低限参照できると嬉しいファイ ルに絞るのが良い。

  17. Thank you Twitter: @biga816 Qiita: biga816