ServiceWorker ã«ã¤ãã¦(2)
ç®æ¨
ServiceWorker ã§Pushéç¥ãåãåãã
å
容çã«ã¯ä¸è¨ã®è¨äºã®ç¶ãã
ç®æ¬¡
- ç®æ¨
- ç®æ¬¡
- ãã¬ã¼ã ã¯ã¼ã¯ã¤ã³ã¹ãã¼ã«
- å®è£
- èµ·åãã¦ã¿ã
- Push éç¥ãéã£ã¦ã¿ãã
å°ãåèã¯ãã
ãã¬ã¼ã ã¯ã¼ã¯ã¤ã³ã¹ãã¼ã«
ã¾ã㯠nodejs
ã§ãµã¼ããä½ãã
npm init
ã¨ã ãæã¡è¾¼ãã§ç©ºã®ããã±ã¼ã¸ãä½æããã
次ã«ãã¬ã¼ã ã¯ã¼ã¯ãã¤ã³ã¹ãã¼ã«ããã
npm i compression
npm i express
npm i web-push
ã³ã¬ã ãã§ãããä¸ç¬ã§ãããï¼
å®è£
ãããªæãã®é ç½®ã§ãã¡ã¤ã«ãä½ã
- root
- public
- js
vapid_demo.js
: åæåç諸ã
index.html
: ç»é¢sw.js
: ãµã¼ãã¹ã¯ã¼ã«ã¼
- js
index.js
: ã¨ã³ããªãã¤ã³ãpackage.json
: nodejs ã®ç®¡çãã¡ã¤ã«
- public
åãã¡ã¤ã«ã®å®è£
index.js
ã·ã³ãã«ã«å®è£
const compression = require('compression'); const express = require('express'); const webPush = require('web-push'); const app = express(); const port = 3000; // ãµã¼ãèµ·åæã«ãç§å¯éµã¨å ¬ééµãä½æ const vapidKeys = webPush.generateVAPIDKeys(); // Push éç¥æ©è½ãåæå webPush.setVapidDetails( 'mailto:[email protected]', // ã¡ã¼ã«å½¢å¼ã§ã©ãã vapidKeys.publicKey, vapidKeys.privateKey ); app.use(compression()); app.use(express.json()); // å ¬ééµãå¿çããã¢ã¯ã·ã§ã³ app.get('/key', (req, res) => { res.status(200).send(vapidKeys.publicKey); }) // POST ãåãããã5ç§å¾ã« Push éç¥ãéä¿¡ããã¢ã¯ã·ã§ã³ app.post('/webpushtest', (req, res) => { console.log(req.body); try { setTimeout(async _ => { // ã¡ãã£ã¨é 延ããã¦éç¥ await webPush.sendNotification(req.body, JSON.stringify({ title: 'Web Pushéç¥ãã¹ã', })); }, 5000); res.json({ success: true }); } catch (err) { console.log(err); } }) // ä¸è¨URLã§ãããããªããªããpublic ã®ä¸ã表示ãã app.use('/', express.static('public')); app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`); });
index.html
ãã£ã¡ãæ»ã¬ã»ã©ã·ã³ãã«
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>VAPID WebPush Demo</title> </head> <body> <button id="btnWebPushTest">ããã·ã¥éç¥ãã¹ã</button> <script src="js/vapid_demo.js"></script> </body> </html>
vapid_demo.js
Push éç¥ãåãåãããã®åæåãè¡ã£ã¦ãã³ã¼ãã
å ã¿ã«ãããã® subscription
ããµã¼ãå´ã«ä¿åãããã¨ã§ãåå¥ã« Push éç¥åºæ¥ãã£ã½ãã
let convertedVapidKey, subscription; (async _ => { try { const registration = await navigator.serviceWorker.register('/sw.js', { scope: '/' }); // ãµã¼ãã¼å´ã§çæãããããªãã¯ãã¼ãåå¾ããurlBase64ToUint8Array()ã使ã£ã¦Uit8Arrayã«å¤æ const res = await fetch('/key'); const vapidPublicKey = await res.text(); convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey); console.log(`vapidPublicKey: ${vapidPublicKey}`); // (å¤æãã)ãããªãã¯ãã¼ãapplicationServerKeyã«è¨å®ãã¦subscribe subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: convertedVapidKey }); console.log(`subscription : ${JSON.stringify(subscription)}`); // éç¥ã®è¨±å¯ãæ±ãã Notification.requestPermission(permission => { console.log(permission); // 'default', 'granted', 'denied' }); } catch (err) { console.log(err); } })(); btnWebPushTest.onclick = async evt => { if (!subscription) return console.log('sbuscription is null'); await fetch('/webpushtest', { method: 'POST', body: JSON.stringify(subscription), headers: { 'Content-Type': 'application/json', }, }); }; function urlBase64ToUint8Array(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; }
æå¾ã«ãPush éç¥ãåãåãå´
sw.js
self.addEventListener('push', evt => { const data = evt.data.json(); console.log(data); const title = data.title; const options = { body: data.body, icon: 'test.jpg' } evt.waitUntil(self.registration.showNotification(title, options)); }); self.addEventListener('notificationclick', evt => { evt.notification.close(); });
èµ·åãã¦ã¿ã
node index.js
ã¨å©ãã¨ãµã¼ããèµ·åã
ã«ã¢ã¯ã»ã¹ããã¨
å ã¿ã« Chrome ã®éçºè ãã¼ã«ãéããã¨ãã«ãããªã¨ã©ã¼ãåºã¦ããå ´åã以åã® Push éç¥ã®åä¿¡è¨å®ãçãã¦ããä½ããã¦ãã¨æãããã
ãã®å ´åã¯ãéçºè ãã¼ã«ã®ãã¢ããªã±ã¼ã·ã§ã³ãã¿ãããåé¤ãã¦ç»é¢ãéãç´ããã
æåããã¨ãããªãã°ãåãåºãããã
ãµã¼ããããvapidãï¼ä¸èº«ã¯å ¬ééµï¼ãåãåã£ã¦ãèªå·±ã®èå¥æ å ±ãéç¥å ã®ãã¼ã¿ãçæãã¦ããã®ã解ãã
Push éç¥ãéã£ã¦ã¿ãã
ã³ã¬ããµã¼ãã«éä¿¡ããã¨ãNodeJS å´ã§ã³ã¬ã5ç§å¾ã«å¿çãè¿ãã
app.post('/webpushtest', (req, res) => { console.log(req.body); try { setTimeout(async _ => { // ã¡ãã£ã¨é 延ããã¦éç¥ await webPush.sendNotification(req.body, JSON.stringify({ title: 'Web Pushéç¥ãã¹ã', })); }, 5000); res.json({ success: true }); } catch (err) { console.log(err); } })
ãµã¼ãå´ã§åãåã£ã JSON ã¯ã³ã¬
{ endpoint: 'https://fcm.googleapis.com/fcm/send/f7iyB(ä¸ç¥)', expirationTime: null, keys: { p256dh: 'BNï¼ä¸ç¥ï¼', auth: 'hB2fï¼ä¸ç¥ï¼' } }
fcm.googleapis.com
ã® FCM 㯠Firebase Clowd Messaging ã®ç¥ãããã
FCM ã®ä»æ§ã¯ãã¡ããåç
§ã