【Vue.js】PWAでプリキャッシュ・ランタイムキャッシュを使いオフライン対応

今回は、PWA化したアプリをオフライン対応するために、プリキャッシュ(PreCache)とランタイムキャッシュ(RuntimeCache)を設定します。
「所得税・住民税・事業税・国保の計算シミュレーション」では、Google Apps Scriptを使いGoogleSpreadSheetをデータベースの代わりに使ってます。ただ、速度があまり出ないのでここにキャッシュを組み込むことでレスポンスを向上させることが一番の目的です。オフラインでも使えるようになりますし。

PWA化した記事から3ヵ月もたってしまいましたが、やっと検証も終わったので、「所得税・住民税・事業税・国保の計算シミュレーション」も入れ替えることができました。

環境

  • Windows 10 Pro
  • vue cli 3
  • Node 12.8
  • @vue/cli-plugin-pwa

プリキャッシュとランタイムキャッシュの違い

プリキャッシュ(PreCash)

アプリのアセット(js,css,imageなど)をキャッシュする際はこちらを利用します。
こちらはあくまでも、アプリのドメインと一緒の場所に配置しているものが対象です。

ランタイムキャッシュ(RuntimeCache)

サードパーティ製のJSやCSSをキャッシュしたい場合や、APIへのリクエストをキャッシュしたい場合はRuntimeCacheを使います。
CDNで参照しているJS・CSSをキャッシュする場合は、プリキャッシュではなくランタイムキャッシュを使用しなければいけません。

プリキャッシュ(PreCash)の導入

@vue/cli-plugin-pwaでPWAを導入したのであれば、とくに設定しなくても自動でキャッシュしてくれます。

必要であれば、ファイルパターンを指定してあげれば良いみたい。
前回の記事からの続きですので、workboxのGenerateSWで進めていきます。

vue.config.js

module.exports = { … configureWebpack: config => { config.plugins.push( new GenerateSW({ cacheId: 'calc-tax-insurance-v3', // vue/cli-plugin-pwaを使ってれば不要 // globPatterns: ['dist/*.{js,png,html,css}'] }) ) }

動作確認

プリキャッシュ無し

当たり前ですがネットワークから取得されてます。

precache-image1

プリキャッシュあり

size部がServiceWorker表示に切り替わりました。

precache-image2

Applicatin-Cache Storageで、precacheされているファイルが確認できます。

precache-image3

オフラインでどうなるか試してみます。
Chromeのデベロッパーツールで、オフラインへの切り替えもできるので、テストも簡単です。

Application-Service Workers内に、Offrine切り替え用の設定があるのでチェックを入れることでオフラインになります。

画面をリロードしてみます。(disc cacheから読まないようにCtrl+F5でスーパーリロードします)

precache-image5

画面切り変わりの一瞬だけChromeのオフライン画面が表示されましたが、アプリの画面が崩れず表示されました。
ネットワークを確認してみると、Service Workerから読み込まれているのが確認できました。問題ないですね!

ランタイムキャッシュ(RuntimeCache)の導入

プリキャッシュの次は、ランタイムキャッシュを組み込みます。
一番の目的は、国保や所得税率の読み込みを行っているのAPI部です。

GenerateSWのruntimeCachingオプションで設定します。

vue.config.js

module.exports = { … configureWebpack: config => { config.plugins.push( new GenerateSW({ cacheId: 'calc-tax-insurance-v3', runtimeCaching: [{ urlPattern: /^https:\/\/script\.google\.com\/macros\/s\/xxxxxxxxxx\/exec/, handler: 'staleWhileRevalidate', options: { cacheName: 'api', expiration: { maxEntries: 20, maxAgeSeconds: 60 * 60 * 24 * 30 }, cacheableResponse: { statuses: [0, 200] } } }] }) ) } }
  • urlPattern: APIのURLのパターンを指定します。(GASのURL)
  • handler: キャッシュ戦略。一番重要な部分です。ちなみにstaleWhileRevalidateは、キャッシュから読み込むけど次回用にバックグラウンドで最新を取得しておくという動きになります。
  • options.cacheName: キャッシュする際のきーとなるもので、他と被らないIDにします。
  • options.expiration: キャッシュの有効期限。適切に設定しておかないと後で痛い目見ますのできちんと設定しておきます。
  • options.cacheableResponse.statuses: ここで指定したhttp statusのリクエストをキャッシュします。

cacheableResponse.statusesは、外部js等をキャッシュする場合は指定しておかないといけないみたいです。
試してませんが、404とかがキャッシュされても困るので、きちんと設定しておいた方が無難そう。。

handlerの種類

  • cacheFirst: キャッシュになければネットワークから取得。
  • cacheOnly: 動きとしてはcacheFirstになるようですが、インストール時に必ずキャッシュされるものはこちらを選ぶのが良いとのこと。キャッシュにないという状態がないもの。
  • networkFirst: ネットワークから取得できなければキャッシュを使用。
  • networkOnly: 常にネットワークから取得。キャッシュされては困るものはこちら。
  • staleWhileRevalidate:ページ表示時はキャッシュから取得し、裏側でネットワークから最新を取得。

動作確認

都道府県・地方自治体を選びキャッシュさせてみます。
ネットワークで確認すると、通常のリクエストの後にfetchというのが続きました。なにやら動いてる模様。

runtime-cache-image2

Application-Cache Storageを見てみると、api+サイトURLでキーが作成され、キャッシュされているのが確認できます。

runtime-cache-image1

正しくキャッシュできてるかオフラインで試します。
fetch煮は失敗してますが、service workerから取得したようなログが出て、キャッシュから読み込まれたのが確認できました。

runtime-cache-image3

ちなみに、キャッシュされていない都道府県・地方自治体を選ぶと取得できないエラーが正しく表示されます。

runtime-cache-image6

ランタイムキャッシュも問題なさそうですね!

まとめ

キャッシュ導入で、一旦PWA化の目的を果たすことができました。
キャッシュを上手に使うと、画面表示のレスポンスを向上させることができたり、不要なトラフィックをなくせるので採用するメリットは大きいと感じました。

次は、プッシュ通知をちょっと触ってみる予定~

所得税・住民税・事業税・国保の計算のバージョンアップ

PWA対応と一緒に、下記地域への計算に対応しました。これでやっと東京都は23区すべて対応できました。

東京都

  • 新宿区
  • 文京区
  • 台東区
  • 墨田区
  • 江東区
  • 品川区
  • 目黒区
  • 大田区
  • 世田谷区
  • 渋谷区
  • 中野区
  • 杉並区
  • 豊島区
  • 北区
  • 荒川区
  • 板橋区
  • 練馬区
  • 足立区
  • 葛飾区
  • 江戸川区
  • 八王子市
  • 立川市