LoginSignup
22
20

More than 5 years have passed since last update.

Service Worker入門〜導入方法から事例紹介まで〜@オトナのプログラミング勉強会

Last updated at Posted at 2018-05-09
1 / 33

はじめに

  • Service Workerって聞いたことあります?

Service Workerとは

  • Webページとは別にバックグランドで実行するスクリプト
    • DOMに直接アクセスできない
    • ブラウザを開いていなくても動作可能
    • プログラム可能なネットワークプロキシとして動作可能
    • HTTPS必須(またはlocalhost)

どんな時に使える?

Cache APIやPush API、Fetch APIと一緒に使うとこで下記のようなことが可能になる

  • キャッシュ・アセットの制御
  • プッシュ通知
  • オフライン対応
  • PWA対応

利用事例(1)


利用事例(2)


利用事例(3)


利用事例(4)


どこでも使えるの?


技術紹介


Service Workerのライフサイクル


Service Workerのライフサイクル(1)

  • 1. 登録
    • jsファイルを指定
  • 2. インストール(oninstall)
    • 静的なアセットを読み込んだりする
  • 3. アクティベート(onactivate)
    • このステップが終わるとすコプ内の全てのページのコントロールが完了
    • 初回はコントロールされず、次に読み込まれた際にコントロールされる

1. 登録

navigator.serviceWorker.register('/sw.js').then(function(registration) {
    console.info('registration', registration);
})

2. インストール(oninstall)

self.addEventListener('install', function (e) {
    console.info('install', e);
});

2. アクティベート(onactivate)

self.addEventListener('activate', function (e) {
    console.info('activate', e);
});

Service Workerのライフサイクル(2)

  • ブラウザスレッド⇔Service Worker間のイベント
    • フェッチ(onfetch)
      • クライアントからサーバーアクセスの際に呼ばれる
    • メッセージ(onmessage)
      • ブラウザスレッドのメソッドからのメッセージング

Service Workerのライフサイクル(3)

  • ブラウザーネットワーク⇔Service Worker間のイベント
    • シンク(onsync)
      • オンライン時に呼ばれる
    • プッシュ(onpush)
      • プッシュ通知を受け取った時に呼ばれる

ハンズオン①

  • Servie Workerを登録&起動の確認

事前準備

  • npmがインストールされている(または、何かしらの言語でサーバーがたてられればOK)
  • 開発はChromeのゲストモード
  • 最終的なレポジトリ

プロジェクトの作成&インストール等

  • プロジェクト作成 
bash
$ mkdir otona_sw
$ cd otona_sw
  • htmlファイルを作成
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>さーびすわーかー</title>
</head>
<body>
さーびすわーかー
</body>
</html>
  • package.jsonを作成
package.json
{
  "scripts": {
    "start": "http-server -c-1"
  },
  "devDependencies": {},
  "dependencies": {
    "http-server": "^0.11.1"
  }
}
  • パッケージのインストール&サーバーの起動
$ npm install
$ npm start

スクリーンショット 2018-05-09 18.13.20.png


Service Workerの登録

sw.js

// インストール
self.addEventListener('install', function (e) {
    console.info('install', e);
});

// アクティベート
self.addEventListener('activate', function (e) {
    console.info('activate', e);
});

// フェッチ
self.addEventListener('fetch', function (e) {
    console.info('fetch', e);
});

index.html
<script>
    // Service Worker API が存在しているかをチェック
    if ('serviceWorker' in navigator) {
        console.log('service worker is active');
        navigator.serviceWorker.register('/sw.js').then(function (registration) {
            // 登録成功
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }).catch(function (err) {
            // 登録失敗 :(
            console.log('ServiceWorker registration failed: ', err);
        });
    }
</script>

1回目

スクリーンショット 2018-05-09 18.14.44.png

2回目

スクリーンショット 2018-05-09 18.14.49.png


Service workers

スクリーンショット 2018-05-09 18.16.12.png



ハンズオン②

  • リクエストを横取り&レスポンスを生成

index.html
<!-- ...省略 -->
<body>
<!-- ...省略 -->
<a href="test">横取り!</a>
<!-- ...省略 -->
</body>
sw.js
// ...省略
// フェッチ
self.addEventListener('fetch', function (e) {
    console.info('fetch', e);

    if (e.request.url.indexOf('test') != -1) {
        e.respondWith(new Response('Hello world'));
    } 
});

実行結果

スクリーンショット 2018-05-09 19.30.30.png


ハンズオン③

  • 画像をキャッシュ

注意

  • 一度ゲストモードのブラウザを閉じてください

インストールイベントで画像をキャッシュ

index.html
<!-- ...省略 -->
<body>
<!-- ...省略 -->
<div id="content"></div>
<script>
    // ...省略
    const element = document.querySelector('#content');
    for(let i=1;i<=100;i++){
        const image = document.createElement('img')
        image.setAttribute('src', `https://robohash.org/${i}.png?size=100x100`)

        element.appendChild(image)
    }
    // ...省略
</script>
sw.js
let urlsToCache = [
    '/',
];

for(let i=1;i<=100;i++){
    urlsToCache.push(`https://robohash.org/${i}.png?size=100x100`)
}

// インストール
self.addEventListener('install', function (e) {
    console.info('install', e);
    e.waitUntil(
        caches.open('v1').then((cache) => {
            // 画像をキャッシュ対象に追加
            cache.addAll(urlsToCache)
        })
    )
});

// フェッチ
self.addEventListener('fetch', function (e) {
    console.info('fetch', e);
    e.respondWith(
        caches.match(e.request)
            .then(function (response) {
                    // キャッシュがあったのでそのレスポンスを返す
                    if (response) {
                        console.info(`Using cache: ${e.request.url}`);
                        return response;
                    }
                    return fetch(e.request);
                }
            )
    );

});

1回目と2回目を試す&オフラインで試す

スクリーンショット 2018-05-09 18.49.17.png


参考

22
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
20