Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

by kei4eva4
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


参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした