この記事では、Firebase Cloud Messaging を使用して、Web アプリケーションまたは Web サイトをプッシュ通知付きの PWA に変換する方法を説明します。
現代では、オフライン サポート、プッシュ通知、バックグラウンド同期などの機能を提供するため、ほとんどの Web アプリケーションが PWA (プログレッシブ Web アプリ) に変換されています。 PWA 機能により、Web アプリケーションがよりネイティブ アプリに近くなり、豊かなユーザー エクスペリエンスが得られます。
たとえば、Twitter や Amazon などの大手企業は、ユーザー エンゲージメントを高めるために Web アプリを PWA に変換しました。
PWAとは何ですか?
PWA = (Web アプリ) + (一部のネイティブ アプリ機能)
PWA は同じ Web アプリ (HTML+CSS+JS) です。これは、以前と同様に、すべてのブラウザー上の Web アプリと同じように機能します。ただし、Web サイトが最新のブラウザーに読み込まれる場合は、ネイティブ機能が含まれる場合があります。これにより、Web アプリが以前よりも強力になり、フロントエンドでアセットをプリフェッチしてキャッシュできるため、スケーラビリティも向上し、バックエンド サーバーへのリクエストが削減されます。
PWA と Web アプリの違い
- インストール可能 : Web アプリはネイティブ アプリのようにインストールできます
- Progressive : Web アプリと同じように動作しますが、いくつかのネイティブ機能を備えています
- ネイティブ アプリ エクスペリエンス : ユーザーは、Web アプリをインストールすると、ネイティブのように Web アプリを使用および操作できます。
- 簡単にアクセスできる : Web アプリとは異なり、ユーザーはアクセスするたびに Web アドレスを入力する必要がありません。設置後はワンタップで開けられます。
- アプリケーション キャッシュ : PWA が登場する前は、Web アプリに実装されていた唯一のキャッシュ メカニズムは、ブラウザーでのみ利用できる HTTP キャッシュを使用することでした。しかし、PWA を使用すると、Web アプリでは利用できないクライアント側のコード自体を使用してキャッシュすることができます。
- (App/Play) ストア公開 : PWA は Google Play ストアおよび IOS App Store で公開できます。
アプリケーションを PWA に変換すると、さらに強力になります。
企業が PWA を検討すべき理由
ほとんどのクライアントは私たちに連絡して、最初に Web アプリ ソリューションの開発を依頼し、次に Android および iOS アプリを求めてきます。私たちがやろうとしているのは、別のチームによって Web アプリの同じ機能を Android/IOS アプリに構築することだけですが、これにはより多くの開発コストと市場投入までの時間がかかります。
しかし、クライアントによっては予算が限られている場合や、製品の市場投入までの時間がより重要であると考えている場合もあります。
クライアントの要件のほとんどは、PWA 機能自体で満たすことができます。彼らに対しては、PWA のみを提案し、Playstore にデプロイしたい場合は TWA を使用して PWA を Android アプリとして変換するというアイデアを提供します。
要件が PWA では満たせないネイティブ アプリケーション機能を本当に必要としている場合。クライアントは、必要に応じて両方のアプリケーションを開発できます。しかし、そのシナリオでも。 Android の開発が完了するまで、Play ストアに PWA を展開できます。
例: タイタンアイプラス
当初、彼らは PWA アプリを開発し、TWA (Trusted Web Activity) を使用して Play ストアにデプロイしました。 Android アプリケーションの開発が完了したら。彼らは実際の Android アプリケーションを Play ストアにデプロイしました。 PWA を使用して市場投入までの時間と開発コストの両方を達成しました。
PWAの機能
PWA は、Web アプリケーションにネイティブ アプリのような機能を提供します。
主な機能は次のとおりです。
- インストール可能: ネイティブ アプリと同様にインストールされる Web アプリケーション。
- キャッシュ: アプリケーションのキャッシュが可能であり、これによりアプリケーションのオフライン サポートが提供されます。
- プッシュ通知: プッシュ通知は、ユーザーを当社の Web サイトに誘導するためにサーバーから送信できます。
- ジオフェンシング: デバイスの位置が変更されるたびに、アプリケーションはイベントによって通知を受け取ることができます。
- 支払いリクエスト: ネイティブ アプリのような優れたユーザー エクスペリエンスを備えたアプリケーションでの支払いを有効にします。
さらに多くの機能が将来提供される予定です。
その他の機能は次のとおりです。
- ショートカット: マニフェスト ファイルに追加された、すぐにアクセスできる URL。
- Web 共有 API: アプリケーションが他のアプリケーションから共有データを受信できるようにします。
- バッジ API: インストールされている PWA の通知数を表示します。
- 定期的なバックグラウンド同期 API: ユーザーのデータは、ネットワークに接続されるまで保存されます。
- 連絡先ピッカー: ユーザーの携帯電話から連絡先を選択するために使用されます。
- ファイルピッカー: ローカルシステム/モバイル上のファイルにアクセスするために使用されます。
ネイティブ アプリケーションに対する PWA の利点
ネイティブ アプリは PWA よりもパフォーマンスが高く、PWA よりも多くの機能を備えています。それでも、ネイティブ アプリに比べていくつかの利点があります。
- PWA は、Android、IOS、デスクトップなどのクロスプラットフォームで実行されます。
- 開発コストが削減されます。
- ネイティブ アプリと比較して、機能の導入が簡単です。
- PWA(Webサイト)はSEOに強いので見つけやすい
- HTTPSでのみ動作するため安全
ネイティブ アプリに対する PWA の欠点
- ネイティブアプリと比べて利用できる機能が限られています。
- PWA 機能は、すべてのデバイスのサポートを保証するものではありません。
- PWA は App Store や Play ストアで利用できないため、ブランド力が低いです。
Android Trusted Web Activity(TWA) を使用して、PWA を Android アプリとして Play ストアにデプロイできます。あなたのブランディングに役立ちます。
WebアプリをPWA化するために必要なもの
あらゆる Web アプリまたは Web サイトを PWA に変換します。
- Service-Worker: キャッシュ、プッシュ通知、リクエストのプロキシのための PWA アプリの中核。
- マニフェスト ファイル: Web アプリケーションに関する詳細が含まれています。以前は、ホーム画面にネイティブ アプリのようにアプリケーションをダウンロードしていました。
- アプリのロゴ: アプリのアイコン用の高品質画像 512 x 512 ピクセル。ホーム画面、スプラッシュ画面などで PWA に必要なアプリのロゴ。そのため、何らかのツールを使用して、アプリ用の 1:1 比率の画像セットを作成する必要があります。
- レスポンシブ デザイン: Web アプリは、さまざまな画面サイズで動作するようにレスポンシブである必要があります。
サービスワーカーとは:
Service Worker (クライアント側スクリプト) は、Web アプリと外部の間のプロキシであり、Web アプリにプッシュ通知を配信し、キャッシュをサポートします。
Service Worker は、メインの JavaScript から独立して実行されます。したがって、DOM API にアクセスできません。 IndexedDB API 、 Fetch API 、 Cache Storage API のみにアクセスできます。ただし、メッセージを使用してメインスレッドと通信できます。
Service Worker が提供するサービス:
- 元のドメインからの HTTP リクエストをインターセプトします。
- サーバーからプッシュ通知を受信します。
- アプリケーションのオフライン利用可能性
Service Worker はアプリケーションを制御し、リクエストを操作できますが、独立して実行されます。そのため、中間者攻撃を避けるために、発信元ドメインで HTTPS を有効にする必要があります。
マニフェストファイルとは何ですか
マニフェスト ファイル (manifest.json) には、ブラウザーに伝えるための PWA アプリに関する詳細が含まれています。
- name: アプリケーションの名前
- short_name: アプリケーションの短い名前。提供されている場合
- プロパティ名と short_name の両方を指定すると、ブラウザは short_name を受け取ります。
- description: アプリケーションを説明する説明。
- start_url: PWA の起動時のアプリケーションのホームページを指定します。
- アイコン: ホーム画面などの PWA 用の画像のセット。
- 背景色: PWA アプリケーションのスプラッシュ画面の背景色を設定します。
- 表示: PWA アプリに表示されるようにブラウザー UI をカスタマイズします。
- theme_color: PWA アプリのテーマの色。
- スコープ: PWA で考慮するアプリケーションの URL スコープ。デフォルトは、マニフェスト ファイルが存在する場所です。
- ショートカット: PWA アプリケーションのクイック リンク。
Web アプリを PWA に変換する
デモの目的で、静的ファイルを含む Web サイトのフォルダー構造を作成しました。
- Index.html – ホームページ
-
記事/
- Index.html – 記事ページ
-
著者/
- Index.html – 著者ページ
-
ツール/
- Index.html – ツールページ
-
お得な情報/
- Index.html – お得な情報ページ
すでに Web サイトまたは Web アプリをお持ちの場合は、以下の手順に従って PWA に変換してみてください。
PWA に必要なイメージを作成する
まず、アプリのロゴを 1:1 の比率で 5 つの異なるサイズに切り抜きます。 https://tools.crawlink.com/tools/pwa-icon-generator/ を使用して、さまざまな画像サイズをすばやく取得しました。だからあなたもそれを使うことができます。
マニフェストファイルを作成する
次に、アプリの詳細を含む Web アプリケーション用の manifest.json ファイルを作成します。デモ用に、 Web サイト用のマニフェスト ファイルを作成しました。
{
"name": "",
"short_name": "",
"description": " produces high-quality technology & finance articles, makes tools, and APIs to help businesses and people grow.",
"start_url": "/",
"icons": [{
"src": "assets/icon/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
}, {
"src": "assets/icon/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
}, {
"src": "assets/icon/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
}, {
"src": "assets/icon/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
}, {
"src": "assets/icon/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}],
"background_color": "#EDF2F4",
"display": "standalone",
"theme_color": "#B20422",
"scope": "/",
"shortcuts": [{
"name": "Articles",
"short_name": "Articles",
"description": "1595 articles on Security, Sysadmin, Digital Marketing, Cloud Computing, Development, and many other topics.",
"url": "/articles",
"icons": [{
"src": "/assets/icon/icon-152x152.png",
"sizes": "152x152"
}]
},
{
"name": "Authors",
"short_name": "Authors",
"description": " - Authors",
"url": "/authors",
"icons": [{
"src": "/assets/icon/icon-152x152.png",
"sizes": "152x152"
}]
},
{
"name": "Tools",
"short_name": "Tools",
"description": " - Tools",
"url": "/tools",
"icons": [{
"src": "/assets/icon/icon-152x152.png",
"sizes": "152x152"
}]
},
{
"name": "Deals",
"short_name": "Deals",
"description": " - Deals",
"url": "/deals",
"icons": [{
"src": "/assets/icon/icon-152x152.png",
"sizes": "152x152"
}]
}
]
}
Service Worker を登録する
スクリプト ファイル register-service-worker.js および service-worker.js をルート フォルダーに作成します。
最初の register-service-worker.js は、DOM API にアクセスできるメイン スレッドで実行される JavaScript ファイルです。ただし、service-worker.js はメインスレッドから独立して実行される Service Worker スクリプトであり、その寿命も短いです。イベントがサービス ワーカーを呼び出すたびに実行され、プロセスが終了するまで実行されます。
メインスレッドのJavaScriptファイルを確認することで、Service Workerが登録されているかどうかを確認できます。そうでない場合は、Service Worker スクリプト (service-worker.js) を登録できます。
以下のスニペットを register-service-worker.js に貼り付けます。
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js');
});
}
以下のスニペットをservice-worker.jsに貼り付けます。
self.addEventListener('install', (event) => { // event when service worker install
console.log( 'install', event);
self.skipWaiting();
});
self.addEventListener('activate', (event) => { // event when service worker activated
console.log('activate', event);
return self.clients.claim();
});
self.addEventListener('fetch', function(event) { // HTTP request interceptor
event.respondWith(fetch(event.request)); // send all http request without any cache logic
/*event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event. request);
})
);*/ // cache new request. if already in cache serves with the cache.
});
オフライン サポートのためにキャッシュを有効にする方法には重点を置きませんでした。ここでは、Web アプリを PWA に変換する方法についてのみ説明します。
HTML ページの all head タグにマニフェスト ファイルとスクリプトを追加します。
追加した後、ページを更新します。これで、以下のようにアプリケーションをモバイル Chrome にインストールできるようになります。

ホーム画面にアプリが追加されます。

WordPress を使用している場合。既存の PWA コンバータ プラグインを使用してみてください。 vueJS または ReactJS の場合は、上記の方法に従うか、既存の PWA npm モジュールを使用して開発を迅速化できます。 PWA npm モジュールはオフライン サポート キャッシュなどですでに有効になっているためです。
プッシュ通知を有効にする
Web プッシュ通知はブラウザーに送信され、ユーザーがアプリケーションをより頻繁に操作/操作できるようになります。を使用して有効にできます
アプリケーションでプッシュ通知を有効にする最初のステップは、通知 API を確認し、ユーザーから通知を表示する許可を取得することです。そのために、以下のスニペットをコピーして register-service-worker.js に貼り付けます。
if ('Notification' in window && Notification.permission != 'granted') {
console.log('Ask user permission')
Notification.requestPermission(status => {
console.log('Status:'+status)
displayNotification('Notification Enabled');
});
}
const displayNotification = notificationTitle => {
console.log('display notification')
if (Notification.permission == 'granted') {
navigator.serviceWorker.getRegistration().then(reg => {
console.log(reg)
const options = {
body: 'Thanks for allowing push notification !',
icon: '/assets/icons/icon-512x512.png',
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: 0
}
};
reg.showNotification(notificationTitle, options);
});
}
};
すべてが正しく進んだ場合。アプリから通知が届きます。


ウィンドウ内の「通知」は、 そのブラウザで通知 API がサポートされていることを示します。 Notice.permission は、 ユーザーが通知を表示することを許可されていることを示します。ユーザーがアプリケーションを許可した場合、値は「許可」されます。ユーザーが拒否した場合、値は「ブロック」されます。
Firebase Cloud Messaging を有効にしてサブスクリプションを作成する
ここからが本当の部分の始まりです。サーバーからユーザーに通知をプッシュするには、ユーザーごとに一意のエンドポイント/サブスクリプションが必要です。そのために、Firebase クラウド メッセージングを使用します。
最初のステップとして、このリンク https://firebase.google.com/ にアクセスして Firebase アカウントを作成し、[開始] をクリックします。
- 名前を付けて新しいプロジェクトを作成し、続行を押します。 という名前で作成してみます。
- 次のステップでは、Google Analytics がデフォルトで有効になります。今は必要ないことに切り替えて、続行を押してください。必要に応じて、後で Firebase コンソールで有効にすることができます。
- プロジェクトが作成されると、以下のようになります。

次に、プロジェクト設定に移動し、クラウド メッセージングをクリックしてキーを生成します。

上記の手順により、3 つのキーを取得しました。
- プロジェクトサーバーキー
- Web プッシュ証明書の秘密鍵
- Web プッシュ証明書の公開鍵
次に、以下のスニペットを register-service-worker.js に貼り付けます。
const updateSubscriptionOnYourServer = subscription => {
console.log('Write your ajax code here to save the user subscription in your DB', subscription);
// write your own ajax request method using fetch, jquery, axios to save the subscription in your server for later use.
};
const subscribeUser = async () => {
const swRegistration = await navigator.serviceWorker.getRegistration();
const applicationServerPublicKey = 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY'; // paste your webpush certificate public key
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey
})
.then((subscription) => {
console.log('User is subscribed newly:', subscription);
updateSubscriptionOnServer(subscription);
})
.catch((err) => {
if (Notification.permission === 'denied') {
console.warn('Permission for notifications was denied')
} else {
console.error('Failed to subscribe the user: ', err)
}
});
};
const urlB64ToUint8Array = (base64String) => {
const padding = '='.repeat((4 - base64String.length % 4) % 4)
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/')
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
};
const checkSubscription = async () => {
const swRegistration = await navigator.serviceWorker.getRegistration();
swRegistration.pushManager.getSubscription()
.then(subscription => {
if (!!subscription) {
console.log('User IS Already subscribed.');
updateSubscriptionOnYourServer(subscription);
} else {
console.log('User is NOT subscribed. Subscribe user newly');
subscribeUser();
}
});
};
checkSubscription();
以下のスニペットをservice-worker.jsに貼り付けます。
self.addEventListener('push', (event) => {
const json = JSON.parse(event.data.text())
console.log('Push Data', event.data.text())
self.registration.showNotification(json.header, json.options)
});
これでフロントエンドの設定がすべて完了しました。サブスクリプションを使用すると、プッシュ サービスが拒否されない限り、いつでも好きなときにユーザーにプッシュ通知を送信できます。
Node.js バックエンドからプッシュする
web-push npm モジュールを使用すると、これを簡単に行うことができます。
NodeJS サーバーからプッシュ通知を送信するスニペットの例。
const webPush = require('web-push');
// pushSubscription is nothing but subscription that you sent from your front-end to save it in DB
const pushSubscription = {"endpoint":"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABh2…E0mTFsHtUqaye8UCoLBq8sHCgo2IC7UaafhjGmVCG_SCdhZ9Z88uGj-uwMcg","keys":{"auth":"qX6AMD5JWbu41cFWE3Lk8w","p256dh":"BLxHw0IMtBMzOHnXgPxxMgSYXxwzJPxpgR8KmAbMMe1-eOudcIcUTVw0QvrC5gWOhZs-yzDa4yKooqSnM3rnx7Y"}};
//your web certificates public-key
const vapidPublicKey = 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY';
//your web certificates private-key
const vapidPrivateKey = 'web-certificate private key';
var payload = JSON.stringify({
"options": {
"body": "PWA push notification testing fom backend",
"badge": "/assets/icon/icon-152x152.png",
"icon": "/assets/icon/icon-152x152.png",
"vibrate": [100, 50, 100],
"data": {
"id": "458",
},
"actions": [{
"action": "view",
"title": "View"
}, {
"action": "close",
"title": "Close"
}]
},
"header": "Notification from -PWA Demo"
});
var options = {
vapidDetails: {
subject: 'mailto:your-actual-mail@gmail.com',
publicKey: vapidPublicKey,
privateKey: vapidPrivateKey
},
TTL: 60
};
webPush.sendNotification(
pushSubscription,
payload,
options
).then(data => {
return res.json({status : true, message : 'Notification sent'});
}).catch(err => {
return res.json({status : false, message : err });
});
上記のコードは、サブスクリプションにプッシュ通知を送信します。サービスワーカーのプッシュ イベントがトリガーされます。
PHP バックエンドからのプッシュ
PHP バックエンドの場合は、 web-push-php コンポーザー パッケージを使用できます。以下のプッシュ通知を送信するサンプルコードを確認してください。
array (
'body' => 'PWA push notification testing fom backend',
'badge' => '/assets/icon/icon-152x152.png',
'icon' => '/assets/icon/icon-152x152.png',
'vibrate' =>
array (
0 => 100,
1 => 50,
2 => 100,
),
'data' =>
array (
'id' => '458',
),
'actions' =>
array (
0 =>
array (
'action' => 'view',
'title' => 'View',
),
1 =>
array (
'action' => 'close',
'title' => 'Close',
),
),
),
'header' => 'Notification from -PWA Demo',
);
// auth
$auth = [
'GCM' => 'your project private-key', // deprecated and optional, it's here only for compatibility reasons
'VAPID' => [
'subject' => 'mailto:your-actual-mail@gmail.com', // can be a mailto: or your website address
'publicKey' => 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY', // (recommended) uncompressed public key P-256 encoded in Base64-URL
'privateKey' => 'your web-certificate private-key', // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
],
];
$webPush = new WebPush($auth);
$subsrciptionData = json_decode($subsrciptionJson,true);
// webpush 6.0
$webPush->sendOneNotification(
Subscription::create($subsrciptionData),
json_encode($payloadData) // optional (defaults null)
);
結論
Web アプリケーションの PWA への変換についてのアイデアが得られれば幸いです。この記事のソース コードは ここで 確認でき、デモは ここで 行えます。サンプルコードも使用して、バックエンドからプッシュ通知を送信してテストしました。