プログレッシブ ウェブアプリに興味があり、まずは Service Worker について調べたことをまとめてみました。
目次
Service Workerとは
- ブラウザが Webページとは別にバックグラウンドで実行するスクリプト。
- プッシュ通知、バックグラウンド同期、オフライン機能などが提供されている。
- オフライン機能では、AppCacheの問題点(複数ページで構成されたサイトでうまく動作しないなど)を改善するように設計されている。
Service Workerのポイント
- JavaScript Workerの一つのため、DOMに直接アクセスできない。
- 状態は、起動しているか、終了しているかの2つ。
そのため、継続的にデータを Service Worker のライフサイクル間で共有したい場合は、IndexedDB API を使用してデータの保存・読み込みを行う必要がある。 - JavaScript の Promises を多用する。
- Httpsが必須(localhostではhttps://localhostでテストできる)。
Service Workerのライフサイクル
Webページとは異なるライフサイクルで動作する。
<ライフサイクル>
1. 対象のWebページにJavaScriptを登録
2. Service Workerのインストール
3. Service Workerののアクティベート
4. 起動か終了の状態になる
1. 対象のWebページにJavaScriptを登録
Service Workerをインストールするために、対象のWebページにService WorkerのJavascriptを登録する必要がある。
2. Service Workerのインストール
JavaScriptが登録されると、ブラウザは Service Worker のインストール処理をバックグラウンドで実行する。
インストール時の処理で、必要なファイルをキャッシュする。
もし、1ファイルでもダウンロードに失敗、もしくはキャッシュに失敗した場合、インストールは失敗する。
3. Service Workerののアクティベート
Service Workerが、スコープ内のすべてのページをコントロールできるようになる。
ただし、Service Worker を登録したページは、この時点ではコントロールできず、次回の読み込みでコントロールできるようになる。
また、不要なキャッシュは、アクティベート処理で削除する。
4. 起動か終了の状態になる
状態は起動・終了の2つのみ。
起動:fetch・message イベントによってService Workerは起動され処理を行う。
終了:メモリ節約のため、イベント処理の実施後は終了します。
Service Worker のスコープ
registerで登録したJavascriptが保存されている階層以下がスコープになる。(fetchイベントを受け付ける)
例)
register(/serviceworker.js)
ドメインルート以下の全てがスコープになる。
register(/hoge/serviceworker.js)
/hoge/ 以下の全てがスコープになる。
Service Worker のテスト
ブラウザのシークレットウインドウで行うのがオススメ。
シークレットウィンドは閉じると、登録やキャッシュが全て消去されるため、以前のテストの影響を受けなくすることができる。
Service Worker 登録のポイント
Service Workerの 登録 に使用する(register)は 、 複数回実行してもブラウザがインストール状態を確認してインストール済みの場合は、再インストールは行われない。
Service Worker インストールのポイント
キャッシュさせたいファイルがある場合は、インストールイベントで行う。
インストールイベントのコールバックを定義して、キャッシュさせたいファイルを指定します。
1 |
self.addEventListener('install', function(event) {}); |
また、コールバック関数では、次のことを行います。
- キャッシュを開く。
- 必要なファイルをキャッシュする。
- 必要なアセットがすべてキャッシュされたかを確認する。
Service Worker 更新のポイント
更新方法
Service Worker の Javascript ファイルを更新します。
ブラウザはサイトに移動した際に、Service Workerを定義するJSファイルを再ダウンロードしようとする。
実際にダウンロードするかの判断は、ブラウザが保持しているJSファイルと、サイトのJSファイルにバイト差異がある場合、新しいものと認識されダウンロードされる。
更新の流れ
1. ブラウザが 新しいService Workerが定義されているJSファイルをダウンロードすると、 Service Worker がスタートし、インストールイベントが発火する。
2. ただし、インストールイベントが発火してもすぐに 新しいService Worker が有効にはならない。
更新用のJSファイルをダウンロードしたページ自体は、古い Service Worker コントロールしているため、新しい Service Worker は waiting 状態になる。
3. このページが閉じられた時点で、古いService Worker は終了し、新しいService Worker がページをコントロールでき、activate イベントが発火する。
更新処理で行う処理
activateのコールバックで古いキャッシュの削除を行う。
理由
新しいService Workerをインストールしても、インストールを実施したページでは、古いService Worker が有効になっている。
そのため、新しい Service Worker は、インストールが完了しても、古い Service Worker が存在するため、 waiting状態になる。
仮に、新しい Service Worker のインストール時に、古いService Workerのキャッシュを削除してしまうと、古い Service Worker が本来必要としているキャッシュを提供できなくなる。
そのため、
キャッシュの登録:インストールのコールバック
キャッシュの削除:アクティベートのコールバック
で行うのが望ましい。
Service Workerがfetch を受け取るタイミング
Service Worker がインストールされた状態で、他ページヘ移動・ページの更新などで、Service Worker は fetch イベントを受け取る。
その他
ブラウザの実装状況を確認
is Serviceworker ready で確認できる。
https://jakearchibald.github.io/isserviceworkerready/
Service Worker が有効になっているかの確認
chromeのアドレスバーに以下を入力
chrome://inspect/#service-workers
Service Worker の詳細を確認
chromeのアドレスバーに以下を入力
chrome://serviceworker-internals
もしくは
chrome://inspect/#service-workers
まとめ
なかなか、ボリュームがある感じですがライフサイクルに気をつけて、各ステージで”何をすべきか”を考えて設計すると、そこまでハマらないような気がしました。
参考にさせていただいたサイト
https://developers.google.com/web/fundamentals/primers/service-workers/?hl=ja