PWA: Workbox Precaching 和訳 (その1)


プリキャッシング

参照元ページ: https://developers.google.com/web/tools/workbox/modules/workbox-precaching

プリキャッシングとは何か?

サービスワーカーには、ファイル一式をキャッシュに保存する機能があります。サービスワーカーが実際に使われる前(インストール時)にコンテンツをキャッシュすることから、この機能は「プリキャッシング」と呼ばれます。(補足: ここで重要なのはインストール時です。install時のキャッシュはプリキャッシュ、fetch時のキャッシュはランタイムキャッシュと呼ばれます)

プリキャッシングによって、ディベロッパーはキャッシュをコントロールできます。つまり、ファイルのキャッシュ有効期間の設定や非ネットワーク経由からファイルを提供することを可能にします。これによりオフラインで動くウェブアプリを作ることができます。(補足: オフラインで最低限必要なファイル、htmlやフォールバック画像やページの見た目を担保するcssやjsファイルをプリキャッシュするのが一つの使い方としてありそうです。)

WorkboxはAPIを簡易化し、ファイル一式のダウンロードを効率的に行えるようにすることで、手間のかかるプリキャッシングの設定をよしなに行なってくれます。

workbox-precachingの仕組み

ウェブアプリケーションが初めて読み込まれた時、workbox-precachingはあなたが読み込みたいすべてのファイルを見にいきます。関連するサービスワーカーイベントを発火し、ファイルを重複なくダウンロードそして保存し、変更情報をIndexedDBのリビジョン*に保存します。

*補足1: リビジョンとはキャッシュされたファイル各々に紐づけられたバージョン(状態の単位)のようなものです。

*補足2: プリキャッシュの情報は配列で管理されます。


あるユーザーがあなたのサイトに再訪問し、サービスワーカーとプリキャッシュされたファイル一式が前回訪問時から異なっている場合を考えてみます。このときworkbox-precachingは新しいプリキャッシュの配列(リスト)を見て、revisionと照らし合わせながらどのファイルが新しいもの、更新されたものかを判断します。サービスワーカーのインストール時にキャッシュファイルは更新され、IndexedDBに新しいrevisionが記録されます。


*補足
プリキャッシュの流れ

1. サービスワーカーがプリキャッシュに指定されているリストを見にいく


[
    {
        url: '/css/styles.css',
        revision: '12345678'
    },
    {
        url: '/js/script.js',
        revision: '23456789'
    },
    {
        url: '/img/image.jpg',
        revision: '34567890'
    }
]

2. IndexedDB内の情報を見にいく。revisionが変更されているか見にいく


[
    {
        url: '/css/styles.css',
        revision: '45678901' // revisionの値が変わっているので、ネットワークからダウンロードする
    },
    {
        url: '/js/script.js',
        revision: '56789012' // revisionの値が変わっているので、ネットワークからダウンロードする
    },
    {
        url: '/img/image.jpg',
        revision: '34567890' // 変更がない 
    },
    {
        url: '/img/image2.jpg',
        revision: '67890123' // このファイルは存在しないので削除
    }
]

実際にDevtoolのApplicationタブでIndexedDBを見るとこのような感じでキャッシュ情報が保存されているのがわかります。

// 補足ここまで

-

新しいサービスワーカーはactivateイベントがトリガーされ、activated(日本語厳しくなってきたのでここは英語にします)状態になるまで利用されることはありません。activateイベント中にworkbox-precachingは古いキャッシュファイルを見にいき、キャッシュとIndexedDBから削除します。