生Service WorkerからWorkboxに乗り換える

Task

2018年10月22日 17:54

2回にかけてService Workerの挙動について理解を進めてきたが、install・activate・fetch等のイベントをサイトに応じて1からスクリプトを書いていくことや、大規模Webサービスでは何をキャッシュしキャッシュしないのかを全て羅列していくのは負担がかかる。
そこで現在は[Workbox]というService Workerのイベントやキャッシュ戦略を簡単にコーディングできるようにするライブラリをGoogleが提供している。
PWA開発の決め手となった[日経電子版PWA化の記事]では開発当時まだWorkboxのようなライブラリが存在せず苦労したとあるが、今ライブラリがあるのならば使ったほうが明らかに開発速度は向上するので、Workboxを採用する。
Workboxに関する日本語記事はまだ少ないので、公式のドキュメントをGoogle翻訳で読みながら実際に動かして試していく。
Service Workerの登録自体は以前と同様だがService Worker本体のコードが少し変わってくる。 sw.js(Service Workerのスクリプト)に以下のように記述する。 ```javascript importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.6.1/workbox-sw.js'); if (workbox) { console.log(`Yay! Workbox is loaded `); } else { console.log(`Boo! Workbox didn't load `); } ``` 実行する(サイトにアクセスする)とCDNからWorkboxを取得し、ロードが完了したかどうかを判別する。 ChromeのデベロッパツールのNetworkタブを見るとworkbox-sw.js, workbox-routing.dev.js, workbox-core.dev.js, workbox-strategies.dev.jsをダウンロードして来ているのが分かる。
先程のsw.jsに以下の様に追記するだけでルートディレクトリのコンテンツを全てキャッシュし、オフラインでも表示可能になる。 ```javascript workbox.routing.registerRoute( /* /(ドメインや各リソース)/ ローカルで開発しているのでホストポートのポートを指している。正規表現が使える!!(神) */ /localhost:8888/, workbox.strategies.staleWhileRevalidate() ); ``` たったの数行で[前々回]のactivate, fetchイベントの記述を網羅している。
またstrategies.staleWhileRevalidate()はサイトに変更がなかった場合キャッシュからDOMを構成するし、変更があった場合キャッシュを行う。この他にstrategies(キャッシュ戦略)には4種類あるが、strategies.staleWhileRevalidate()がService Workerを利用する上で理想的な動き方をしている。
installイベントのプリキャッシュを行っていないので、実際に動作の流れとしては、workbox-sw.jsのインポート(訪問1回目)→コンテンツのキャッシュ(2回目)→キャッシュからコンテンツの読み出し(3回目以降) となっている。
installイベントのときにプリキャッシュを行うことで、訪問1回目の時点でコンテンツのキャッシュを行うことができる。 ```javascript workbox.precaching.precacheAndRoute([ './', './css/stylesheet.css', './js/javascript.js' // etc...... ]); ``` 問題としてこちらは正規表現で指定ができない(?)ので、各リソースを指定する必要がある。 [Workbox]: https://developers.google.com/web/tools/workbox/ [日経電子版PWA化の記事]: https://employment.en-japan.com/engineerhub/entry/2018/06/05/110000 [前々回]: https://hi97.hamazo.tv/e8213082.html
document.getElementById("mdrender").innerHTML = marked(document.getElementById("mdraw").innerHTML); const tags = document.getElementById("mdrender").querySelectorAll("a"); for (let tag of tags) { tag.setAttribute("target", "_blank"); }

関連記事