ServiceWorkerでsvgを書き換えるメモ

twitterLiteのようなプログレッシブウェブアプリが作りたいのでServiceWorkerを使ってみました 面白いけど、ちょっと癖があるのでメモ
とりあえずProxyが面白そうなので今日はそのサンプルを載せます

そもそもServiceWorkerて何?

正しい説明はググってください
ポイントはJSをURLに紐づくカタチでインストールできること
インストールすることにより起動時にjsをDLする必要がなくなるため、バックグラウンド処理などができるようになる

index.html

<!DOCTYPE html>
<script>
// ServiceWorkerのセットアップ
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('sw.js', {scope: './'}).then(function(registration) {
    // registration worked
    console.log('Registration succeeded.');
  }).catch(function(error) {
    // registration failed
    console.log('Registration failed with ' + error);
  });
};
</script>

<!-- SVG画像の表示 -->
<img src="img/hoge.svg" />

序盤のscriptがServiceWorkerの設定
sw.jsを読み込んでる
最後のimgタグにhoge.svgを読み込む
ただしこの画像ファイルは用意しない
この画像をServiceWorker側で生成するのが今回のゴール

sw.js

/**
 * ダミーのsvgを作成する
 * @return {Response}
 */
function createDummySvgResponse() {
  let headers = new Headers();
    headers.append('Content-Type', 'image/svg+xml');
    let body = `<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" stroke="#000" fill="none" /></svg>`
    return new Response(body, {headers})
}

// htmlからリクエストが飛ぶと呼ばれる
// 通常はここでweb上のファイルを取りに行くが
// それをフックしてダミーのsvgファイルを返す
self.addEventListener('fetch', function(event) {
  if (event.request.url.indexOf('hoge.svg') != -1) {
    const response = createDummySvgResponse()
    event.respondWith(response);
    return
  }
  
  // 上記if文に入らなかったものは、普通にwebから取得される
});

selfって何だ!?て思うけど、まぁそうゆう変数があるんでしょうってことでスルーw

実行時の落とし穴

ServiceWorkerはHTTPSlocalhostでしか動作しない
なのでindex.htmlを直接ブラウザで開いても動作しません
ローカルで試すならnpmでhttp-serverとか入れるといい
あと、一度インストールするとコードを修正してもそれが反映されなくなるのでDevToolのServiceWorkerの設定でupdate on reloadにチェックを入れる必要があります

実行

index.htmlを表示すると
sw.jsに書いてある丸いsvg画像が表示されました

感想

インストールしちゃうところが面白い
index.html以外のファイルを自在に操れるからDIもここでやるのかなぁ
ただ実装箇所が通常のjsとSeviceWorkerの2つになるので設計的には難しそう