既存サイトにPWAを導入する(オフライン対応・プッシュ通知)

Web制作 2018.01.12

Android対応

1.マニフェスト記述

ホーム画面に追加したアイコンから起動した場合の表示の制御
アイコン画像やアプリの名前、ステータスバーの表示、縦画面横画面など

(Androidのみ)





<link rel="manifest" href="/manifest.json">
{
  "name"              : "PWATEST",
  "short_name"        : "PWATESTSHORTNAME",
  "description"       : "PWA DESCRIPTION",
  "start_url"         : "/",
  "display"           : "standalone",
  "orientation"       : "any",
  "background_color"  : "#f44336",
  "theme_color"       : "#f44336",
  "gcm_sender_id": "*********",
  "icons": [
		{
      "src"           : "/images/logo/logo072.png",
      "sizes"         : "72x72",
      "type"          : "image/png"
    },
		{
      "src"           : "/images/logo/logo152.png",
      "sizes"         : "152x152",
      "type"          : "image/png"
    },
		{
      "src"           : "/images/logo/logo192.png",
      "sizes"         : "192x192",
      "type"          : "image/png"
    },
		{
      "src"           : "/images/logo/logo256.png",
      "sizes"         : "256x256",
      "type"          : "image/png"
    },
		{
      "src"           : "/images/logo/logo512.png",
      "sizes"         : "512x512",
      "type"          : "image/png"
    }
	]
}

2.ServiceWorkerの登録

windowロード時火
同時に通知を許可するかどうかの確認アラート
一度通知を許可しないを選択した場合、その後ユーザー側で操作しない限り再度通知のアラートは出せない

対応していない端末では登録されない
→ios(safari,chorome)では登録されない

PUSH通知参考
https://www.mitsue.co.jp/knowledge/blog/frontend/201708/28_1146.html

(function() {
	'use strict';
	// unsupported browser
	if (!window.addEventListener || !window.history || !window.requestAnimationFrame || !document.getElementsByClassName) return;
	// enable service worker
	if ('serviceWorker' in navigator) {
		navigator.serviceWorker.register('/service-worker.js').then(function(reg) {
			reg.pushManager.subscribe({userVisibleOnly: true}).then(function(sub) {
			  console.log(sub.endpoint);
			});
		}).catch(function(error) {
			console.log(error);
		});
	}
})();

3.Serviceworker中身

通知をJSON形式で取得する方法不明

'use strict';

const CACHE_NAME = 'cache-v1';
const urlsToCache = [
    './',
    'manifest.json',
];

self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open(CACHE_NAME)
              .then((cache) => {
                  console.log('Opened cache');
                  // 指定されたリソースをキャッシュに追加する
                  return cache.addAll(urlsToCache);
              })
    );
});

self.addEventListener('activate', (event) => {
    var cacheWhitelist = [CACHE_NAME];

    event.waitUntil(
        caches.keys().then((cacheNames) => {
            return Promise.all(
                cacheNames.map((cacheName) => {
                    // ホワイトリストにないキャッシュ(古いキャッシュ)は削除する
                    if (cacheWhitelist.indexOf(cacheName) === -1) {
                        return caches.delete(cacheName);
                    }
                })
            );
        })
    );
});

self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request)
              .then((response) => {
                  if (response) {
                      return response;
                  }

                  // 重要:リクエストを clone する。リクエストは Stream なので
                  // 一度しか処理できない。ここではキャッシュ用、fetch 用と2回
                  // 必要なので、リクエストは clone しないといけない
                  let fetchRequest = event.request.clone();

                  return fetch(fetchRequest)
                      .then((response) => {
                          if (!response || response.status !== 200 || response.type !== 'basic') {
                              return response;
                          }

                          // 重要:レスポンスを clone する。レスポンスは Stream で
                          // ブラウザ用とキャッシュ用の2回必要。なので clone して
                          // 2つの Stream があるようにする
                          let responseToCache = response.clone();

                          caches.open(CACHE_NAME)
                                .then((cache) => {
                                    cache.put(event.request, responseToCache);
                                });

                          return response;
                      });
              })
    );
});

self.addEventListener('push', function (event) {
    console.log('Received a push message', event);
    var title = "プッシュ通知です!";
    var body = "プッシュ通知はこのようにして送られるのです";

    event.waitUntil(
        self.registration.showNotification(title, {
            body: body,
            icon: 'http://free-images.gatag.net/images/201108090000.jpg',
            tag: 'push-notification-tag'
        })
    );
});
self.addEventListener('notificationclick', function (event) {
    event.notification.close();
    clients.openWindow("/");
}, false);

4.プッシュ通知

https://sitest.jp/blog/?p=4218

<script src="https://www.gstatic.com/firebasejs/4.8.1/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "**********",
    authDomain: "pwatest-729d1.firebaseapp.com",
    databaseURL: "https://pwatest-729d1.firebaseio.com",
    projectId: "pwatest-729d1",
    storageBucket: "pwatest-729d1.appspot.com",
    messagingSenderId: "*********"
  };
  firebase.initializeApp(config);
</script>

ios対応

2018/01/12
Serviceworkerは未対応

ホーム画面に追加してネイティブアプリの様に表示する

<meta name="apple-mobile-web-app-capable" content="yes">

普通にリンクするとブラウザを起動しての遷移になるのでJSでリンクを設定する必要がある AJAXなど
参考:http://d.hatena.ne.jp/izit_kosuke/20110219/1298073430

オフライン対応

アプリケーションキャッシュを使えばできるらしい

http://techblog.kayac.com/2016/12/12/090000

PUSH通知は無理っぽい

ネイティブアプリを作成する必要がある

参考

https://qiita.com/y_fujieda/items/f9e765ac9d89ba241154#%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB

https://developers.google.com/web/fundamentals/primers/service-workers/?hl=ja

https://www.webprofessional.jp/retrofit-your-website-as-a-progressive-web-app/

https://developers.google.com/web/fundamentals/codelabs/push-notifications/?hl=ja

https://sitest.jp/blog/?p=4218

Hiroshi Uesugi

Toyonaka,Osaka

最後まで読んでいただきありがとうございます!
フロントエンドエンジニアとして、大阪でフリーランスとしてWeb制作をしています。