読者です 読者をやめる 読者になる 読者になる

sekaie engineers' blog

セカイエ株式会社が主催するエンジニア勉強会について

service worker の話

こんちは。

最近もっぱらconfluenceで仕様作成しかしていない増井です。

セカイエアドベントカレンダー5日目!!

qiita.com

サーバーからブラウザに即座に反映

弊社の顧客管理システムの追加仕様を考えていて

サーバー側で変更があったら、即ブラウザに反映したい! ってケースがでてきました。

こうゆう場合の一般的な方法としては、ブラウザ側から一定間隔でサーバーにリクエストなげて、取得してくる。何か変更があればそれを表示する。みたいな方法になると思います。

絶対に変更があるならこれでもいいかもしれませんが、変更がなかったりすると不要なリクエストを投げまくることになりますし、リアルタイムではないです。

これはイケてません。(※今回は最終的にこの方法に +α して対応しました。)

他にも

  • websoket
  • http streaming
  • service worker

いろいろ方法はあるみたいですが、service worker が気になったので試してみます。

service worker

  • オフライン体験
  • 定期的なバックグラウンド同期
  • プッシュ通知

ができる。

アプリみたいですね。

とりえあず取り込んでみます。

注意点

  • httpsじゃないとだめ
  • ブラウザはクロームで(Ver. 40以上)chrome://version/ でcheck!!

大まかな手順

  1. GCMに登録 (google cloud messaging)
  2. manifest.json の作成
  3. push.js の作成
  4. service-worker.js の作成
  5. index.html  の作成
  6. Pushの配信リクエストを投げる

1. GCMに登録 (google cloud messaging)

for Android

for Chrome

があるみたいだから両方有効にする。

f:id:sekaie:20151202124007p:plain

あれ?

for chrome がない!

しょっぱなでつまずく。ひとまず for Android のみでいいか。

なんでだ。取りあえず次へ行こう。

2. manifest.json

{
  "name": "PushTest",
  "short_name": "Pushtest",
  "icons": [{
    "src": "icon.png",
    "sizes": "400x400",
    "type": ""
  }],
  "start_url": "/",
  "display": "standalone",
  "gcm_sender_id": "プロジェクトID"

}

※プロジェクトIDはGCMを登録しているもの。

設定は

<link rel="manifest" href="manifest.json">

でOK。

3.push.js 

別の名前でも可。

function register() {
        // service-worker.jsをService Workerとして登録する
        navigator.serviceWorker.register('./service-worker.js', {
           scope: '.'
        }).then(function onFulfilled () {
            // service-worker.jsがひと通り評価され、インストールが成功した場合
            console.log('Service Worker was installed.');
        }, function onRejected () {
            // service-worker.jsのインストールが失敗した場合
            console.log('Service Worker was not installed.');
        });
}

function setPush() {
  if(!subscription) {
    if(Notification.permission == 'denied') {
      alert('プッシュ通知を有効にできません。ブラウザの設定を確認して下さい。');
      return;
    }
    navigator.serviceWorker.ready.then(subscribe);
  }
  else
    navigator.serviceWorker.ready.then(unsubscribe);
}

function subscribe(sw) {
  sw.pushManager.subscribe({userVisibleOnly: true}).then(
    function(pushSubscription) {
      console.log(pushSubscription.endpoint);
    }, function(error) {
      console.log(error);
    }
  );
}

大事そうな部分のみ抜粋

4.service_worker.js

self.addEventListener('push', function(evt) {
  evt.waitUntil(
    self.registration.showNotification(
      'GET!!NEW!!ITEM!!',
      {
        icon: '/img/icon.gif',
        body: '通知のタイトルーーー',
        tag: 'test_tag'
      }
    )
  );
}, false);

self.addEventListener('notificationclick', function(evt) {
  evt.notification.close();

  evt.waitUntil(
    clients.matchAll({ type: 'window' }).then(function(evt) {
      var p = location.pathname.split('/');
      p.pop();
      p = location.protocol + '//' + location.hostname + (location.port ? ':'+location.port : '') + p.join('/') + '/';
      for(var i = 0 ; i < evt.length ; i++) {
        var c = evt[i];
        if(((c.url == p) || (c.url == p + 'index.html')) && ('focus' in c))
          return c.focus();
      }
      if(clients.openWindow)
        return clients.openWindow('./');
    })
  );
}, false);

5.index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Push API sample</title>
    <link rel="manifest" href="/manifest.json">
    <link rel="javascript" type="text/javascript" href="push.js">

  </head>
  <body>
    <button id="register">インストール</button>
    <button id="push" disabled>有効にする</button>
  </body>
</html>

6. 配信リクエストを投げる

curl --header "Authorization: key=(gcmのkey)" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"(ここにIDいれる)\"]}"

以上。

ほほう これでできるのか。

えい!

{"multicast_id":hogehogehogehogehoge,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}

エラー。

リクエスト投げるときの registration_ids がまちがえてるのか。 そもそもどうやって確認するんやろ。

chrome://serviceworker-internals/

これで登録されてるservice-workerの状態が確認できるみたい。

f:id:sekaie:20151202124342p:plain

たぶんこれやな。15。

curl --header "Authorization: key=(gcmのkey)" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"15\"]}"
{"multicast_id":hogehogehogehogehoge,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}

エラー。だめだ。

ちなみに

f:id:sekaie:20151202124520p:plain

Push してみると

f:id:sekaie:20151202124602p:plain

おおお!

で、何でだめなんだ。 push.js にデバッグいれて確認。

sw.pushManager.subscribe({userVisibleOnly: true})

Registration failed - push service error {}

PUSH通知を有効にできてないみたいやけどなんで?

今回はここまで。

進展あれば更新します!

まとめ

  • 業務では使わなかった
  • 方法いろいろあるけど、service workerつかってみる
  • 取り込みきれなかった
  • PUSH通知を有効にできない理由を探ってservice workerを試す。

感想

試せてないけどservice workerを使うとwebサービスの幅が広がりそうな予感。

  • アラート表示
  • "顧客対応中"といったようなメンバー内での共有通知
  • 顧客側のブラウザにお知らせメールなどの通知

などなど顧客管理以外でも使えそうだ!!

明日はだれかな?

ほな。

広告を非表示にする