質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
npm

npmは、Node Packaged Modulesの略。Node.jsのライブラリ・パッケージを管理できるツールです。様々なモジュールを簡単にインストールでき、自分でモジュールを作成し公開する際にも使用できます。

Babel

Babelは、JavaScriptの次世代仕様であるECMAScriptのコンパイラ。次世代の標準機能を用いて記述されたコードを、それらの機能に対応していないブラウザでも動作するコードに変換することができます。

PWA(Progressive Web Apps)

PWA(Progressive Web Apps)は、アプリのようなWebサイトを指します。仕様が異なる様々なデバイスで表示でき、インストールも不要。さらに訪問し続けることでユーザーについて学び、強力なPWAとなります。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Q&A

0回答

1651閲覧

PWAのプッシュ通知時のトークン処理の稚拙な問題

Fujiman

総合スコア41

npm

npmは、Node Packaged Modulesの略。Node.jsのライブラリ・パッケージを管理できるツールです。様々なモジュールを簡単にインストールでき、自分でモジュールを作成し公開する際にも使用できます。

Babel

Babelは、JavaScriptの次世代仕様であるECMAScriptのコンパイラ。次世代の標準機能を用いて記述されたコードを、それらの機能に対応していないブラウザでも動作するコードに変換することができます。

PWA(Progressive Web Apps)

PWA(Progressive Web Apps)は、アプリのようなWebサイトを指します。仕様が異なる様々なデバイスで表示でき、インストールも不要。さらに訪問し続けることでユーザーについて学び、強力なPWAとなります。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

0グッド

1クリップ

投稿2019/03/01 06:39

編集2022/01/12 10:55

状況

このサイトの「Push Notification編」を参考に
PWAでのプッシュ送信についてひと通りやりました。それに関しては問題なかったのですが
少し変えたいと変更を加えたときに、通知承認のデータを変数に受け取るという
問題が解決できず悩んでいます。
PWAとかNodeとかの以前の問題で、表題とほとんど関連性がないと思いますが・・・

プロジェクト概要

このプロジェクトの概要は、サイトのサービスワーカーに(service-worker.js)、
'push'イベントが発生すると既定の通知内容を表示するハンドラを設定しており、
main.jsではユーザがページにアクセスした際に、通知の承諾をすると
そのEndpoint、Author、Keyをページに表示します。
別途、push.jsというファイルにそれら表示情報を埋め込んで(npmの'web-push'を使ってます)
Nodeで実行しプッシュ通知の送信をするというものです

やろうとしていること

現状ではpush.jsの実行後に通知が表示されますが、これを、ユーザが承諾した時点でプッシュ通知を表示したいと思い、main.js内の、承諾時のデータを画面表示する処理の後にpush.jsの処理を追加しようとしました


main.js(変更前)

js

1if ('serviceWorker' in navigator) { 2 document.addEventListener('DOMContentLoaded', () => { 3 let endpoint = document.querySelector('#subscription-endpoint'); 4 let key = document.querySelector('#subscription-public-key'); 5 let auth = document.querySelector('#subscription-auth'); 6 7 navigator.serviceWorker.register('./service-worker.js'); 8 navigator.serviceWorker.ready 9 .then((registration) => { 10 return registration.pushManager.subscribe({userVisibleOnly: true}); 11 }) 12 .then((subscription) => { 13 var rawKey = subscription.getKey ? subscription.getKey('p256dh') : ''; 14 key.value = rawKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) : ''; 15 var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : ''; 16 auth.value = rawAuthSecret ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) : ''; 17 endpoint.value = subscription.endpoint; 18 console.log(`GCM EndPoint is: ${subscription.endpoint}`); 19 }) 20 .catch(console.error.bind(console)); 21 }, false); 22}
push.js(変更前)

js

1'use strict'; 2let push = require('web-push'); 3const GCM_API_KEY = '略'; 4push.setGCMAPIKey(GCM_API_KEY); 5const data = { 6 'endpoint': '略', 7 'userAuth': '略', 8 'userPublicKey': '略' 9}; 10 11push.sendNotification(data.endpoint, { 12 payload: 'service worker プッシュテスト', 13 userAuth: data.userAuth, 14 userPublicKey: data.userPublicKey, 15}) 16.then((result) => { 17 console.log(result); 18}) 19.catch((err) => { 20 console.error('fail', err); 21}); 22

このmain.js内にpush.jsの内容を埋め込んでみたものが以下です。
画面表示に使っているデータを'web-push'に渡すオブジェクト”data”にセットしているだけです。
これをトランスパイルしてbundle.jsとし、main.jsのかわりにindex.htmlから呼びます
するとコンソールに後述のような'web-push'のエラーが出てしまいます。
ページにはAuth,Key,Endpointが表示されてはいますが。

App.js(main.jsにpush.jsを埋め込んだファイル)

js

1 2'use strict'; 3 4let push = require('web-push'); 5const GCM_API_KEY = '略'; 6push.setGCMAPIKey(GCM_API_KEY); 7let data = { 8 'endpoint': '', 9 'userAuth': '', 10 'userPublicKey': '' 11}; 12 13if ('serviceWorker' in navigator) { 14 document.addEventListener('DOMContentLoaded', () => { 15 let endpoint = document.querySelector('#subscription-endpoint'); 16 let key = document.querySelector('#subscription-public-key'); 17 let auth = document.querySelector('#subscription-auth'); 18 19 navigator.serviceWorker.register('./service-worker.js'); 20 navigator.serviceWorker.ready 21 .then((registration) => { 22 return registration.pushManager.subscribe({userVisibleOnly: true}); 23 }) 24 .then((subscription) => { 25 var rawKey = subscription.getKey ? subscription.getKey('p256dh') : ''; 26 key.value = rawKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) : ''; 27 var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : ''; 28 auth.value = rawAuthSecret ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) : ''; 29 endpoint.value = subscription.endpoint; 30 data.endpoint = endpoint.value; 31 data.userAuth = auth.value; 32 data.userPublicKey = key.value; 33 }).then(() => { 34 push.sendNotification(data.endpoint, { 35 payload: 'service worker プッシュテスト', 36 userAuth: data.userAuth, 37 userPublicKey: data.userPublicKey, 38 }) 39 .then((result) => { 40 console.log(result); 41 }) 42 .catch((err) => { 43 console.error('fail', err); 44 }) 45 }).catch(console.error.bind(console)); 46 }, false); 47} 48
エラー内容

error

1fail Error: "You must pass in a subscription with at least an endpoint." 2 generateRequestDetails web-push-lib.js:89 sendNotification web-push-lib.js:289 [195]</</< App.js:36 3App.js:45:16 4 [195]</</</< App.js:45

少なくともエンドポイントは渡せという意味のエラーだと思うのですが、
なぜ渡せてないのかわからず悩んでいます。

もともとは画面表示しているデータをそのままコピペして実行するpush.jsなので
どうしてこれでまずいのかがわからす悩んでいます。
処理の流れが理解できていない気がします。
オブジェクト”data”の各プロパティーに値がセットされる前に、
そのプロパティーのチェック処理が走っているような感じなのですが

また、あわせて教えていただきたいのですが、後日のプッシュ通知にも使うために
このようにユーザから得た承認のトークンなどの管理は
一般的にはどうしているのでしょうか?
どんどんDataBaseなどに保存していっているのでしょうか?
逆にブラウザの通知設定で削除されたりして承認を得られなくなったら、
その保有していた承認のデータは削除するとかでアップデートし管理しているのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問