masalibの日記

システム開発、運用と猫の写真ブログです

PWA:サービスワーカー導入編

f:id:masalib:20180810173837p:plain

自分用のメモですが何かの参考になれば幸いです。
参考動画を引用しているのが多々あります。 サービスワーカーの概要は過去記事を参考にしてください

masalib.hatenablog.com

サンプルソースをもとにライブラリーなしで導入する記事です。

環境構築

サンプルがあったのそちらをもとにサービスワーカーを実際にいれてみます

git clone https://github.com/webopt/ch9-service-workers.git
cd ch9-service-workers
npm install
node http.js

起動した画面はこちらになる
http://localhost:8080/
f:id:masalib:20180811010422j:plain

この時点では何もサービスワーカーが動いていない f:id:masalib:20180811010446j:plain

ソースの構成は以下のとおりで こちらのsw-install.jsとsw.jsを触っていく f:id:masalib:20180811010503j:plain

htmlの最後にsw-install.jsが読み込まれるようになっている f:id:masalib:20180811010521j:plain

serviceWorker対応チェック

まずはserviceWorkerが対応しているのか確認する

実行結果 f:id:masalib:20180811165117j:plain

コンソールログに成功したログが表示されている。

インストール

実際にサポートされているのがわかったので次はインストールする。
window.addEventListenerのloadイベントをとって関数にわたす(アロー関数)
navigator.serviceWorkerのオブジェクトを利用してインストールする
成功した場合はregにわたされる。失敗した場合はcatchする

f:id:masalib:20180811170937j:plain
アプリケーションのタブを確認するとインストールされている事が確認できる
f:id:masalib:20180811171104j:plain

インストールされたservice worker側が動いているのか確認する

f:id:masalib:20180811172208j:plain

ちなみにリロードするとservice worker側のログは表示されない
activeのイベントを追加する

もしログが表示されない場合はapplicationのタブでService WorkerをUnregistedを実行するとでてくる
この段階ではService Workerにキャッシュされていないのでオフラインにした場合はもちろん動かない

キャッシュファイルの追加

キャッシュさせる名前のファイル名をつける

const cacheName = 'v1';

const cacheAssets = [
  'index.html'
  ,'about-me.html'
  ,'/css/global.css'
  ,'/js/attach-nav.js'
  ,'/js/debounce.js'
  ,'/js/nav.js'
];

1つでもファイル名を間違えるとキャッシュされないみたい・・・

installイベントにHTMLなどをキャッシュさせる行為を追加する

    e.waitUntil(
      caches
        .open(cacheName)
        .then(cache => {
          console.log('Service Worker: Caching Files');
          cache.addAll(cacheAssets);
        })
        .then( () => self.skipWaiting())
    )   

全体は以下のとおり キャッシュさせるとapplicationの所にcacheが追加される。

f:id:masalib:20180811183925j:plain

キャッシュはさせたがこの段階では通信を横取りする機能がないのでオフライン時はエラーになる。

キャッシュファイルの削除

cacheNameで設定した名前でキャッシュされる名前をかえると別名でキャッシュされる

const cacheName = 'v2';     //v1 -> v2

だた前の部分が消えるわけではない。前のキャッシュをクリアする処理をアクティブイベントに追加する

  e.waitUntil(
    caches.keys().then(cacheNames => {
        return Promise.all(
            cacheNames.map(cache => {
              if(cache !== cacheName){
                  console.log('Service Worker: Clearing Old Cache');
                  return caches.delete(cache);
              }
            })
        )
      })
    );    

f:id:masalib:20180811190613j:plain

fetchイベントを追加する(横取り機能)

// Fetchイベント(横取り)
self.addEventListener('fetch',e => {
  console.log('Service Worker: sw.js Fetching ');
  e.respondWith(fetch(e.request).catch(() => caches.match(e.request)));
});

これでオフラインでも表示できるようになる

f:id:masalib:20180811193938j:plain

ちなみに上記の画像のofflineとupdate onloadをクリックしてオフラインにします
全体は以下のとおり

横取り機能をアクセスごとに変更する

すべてのファイルをcacheAssetsに書くのは現実的ではないので fetchイベントに追加して、キャッシュさせる

// Fetchイベント(横取り)
self.addEventListener('fetch',e => {
  console.log('Service Worker: sw.js Fetching ');
  e.respondWith(
    fetch(e.request)
      .then(res => {
        //リクエストのコピーをする
        const resClone = res.clone();
        //キャッシュを開く
        caches
          .open(cacheName)
          .then(cache => {
            cache.put(e.request, resClone);
          });
        return res;
      }).catch(err => caches.match(e.requset).then(res => res)  )
  );
});

インストール時のイベントやcacheAssetsも削除する 全体は以下のとおり

f:id:masalib:20180811201216j:plain

キャッシュされるのが確認できる(オフラインでも使えた)

感想

導入の1からソースを書いたので理解がふかまった。でもソースが長くなりそうなので次回はgoogle先生のライブラリーのWorkboxを使って導入したい。

developers.google.com

参考動画

www.youtube.com