From e5ad87f4d5e3e23f8839a6878972f73ddc9767fe Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Fri, 25 Aug 2023 21:45:55 +0800 Subject: [PATCH] Updates to web push guide --- web-push.md | 77 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/web-push.md b/web-push.md index 5b532ff..7ce3521 100644 --- a/web-push.md +++ b/web-push.md @@ -1,19 +1,19 @@ Web Push notifications is a web browser messaging protocol defined by the W3C. -Discussions of this interesting technology are clouded because of a terminological -morass. +Discussions of this interesting technology are clouded because of a +terminological morass. To understand how Web Push operates, we need to observe that are three (and potentially four) parties involved. These are: 1) The user's web browser. Let's call that BROWSER -2) The Web Push Service Provider which is operated by the organization controlling the -web browser's source code. Here named PROVIDER. An example of a PROVIDER is -FCM (Firebase Cloud Messaging) which is owned by Google. -3) The Web Application that a user is visiting from their web browser. Let's call this the -SERVICE (short for Web Push application service) -[4) A Custom Web Push Intermediary Service, either third party or self-hosted. Called -INTERMEDIARY here.] +2) The Web Push Service Provider which is operated by the organization +controlling the web browser's source code. Here named PROVIDER. An example of a +PROVIDER is FCM (Firebase Cloud Messaging) which is owned by Google. +3) The Web Application that a user is visiting from their web browser. Let's +call this the SERVICE (short for Web Push application service) +[4) A Custom Web Push Intermediary Service, either third party or self-hosted. +Called INTERMEDIARY here.] The workflow works like this: @@ -22,13 +22,18 @@ BROWSER visits a website which has a SERVICE. The SERVICE asks BROWSER for its permission to subscribe to messages coming from the SERVICE. -Provide context and obtain explicit permission before prompting for notification permission: -It is recommended to set up to a two-step opt-in process where the user is first presented -with a pre-permission dialog box that explains what the notifications are for and why they -are useful. This may help reduce the possibility of users clicking "don't allow. +The SERVICE will provide context and obtain explicit permission before prompting +for notification permission: -In Typescript, we can activate a browser's permission dialogue in this manner: +In orer to provide this context and explict permission a two-step opt-in process +where the user is first presented with a pre-permission dialog box that explains +what the notifications are for and why they are useful. This may help reduce the +possibility of users clicking "don't allow. +Now, to explain what happens in Typescript, we can activate a browser's +permission dialogue in this manner: + +``` function askPermission(): Promise { return new Promise(function(resolve, reject) { const permissionResult = Notification.requestPermission(function(result) { @@ -45,14 +50,54 @@ function askPermission(): Promise { return permissionResult; }); } +``` + +If the user grants permission, the client application registers a service worker +using the `ServiceWorkerRegistration` API. + +The `ServiceWorkerRegistration` API is accessible via the browser's `navigator` +object and the `navigator.serviceWorker` child object and ultimately directly +accessible via the navigator.serviceWorker.register method which also creates +the service worker or the navigator.serviceWorker.getRegistration method. + +Once you have a `ServiceWorkerRegistration` object, that object will provide a +child object named `pushManager` through which subscription and management of +subscriptions may be done. -If the user grants permission, the client application registers a service worker using -the ServiceWorkerRegistration API. +Let's go through the `register` method first: +``` +navigator.serviceWorker.register('sw.js', { scope: '/' }) + .then(function(registration) { + console.log('Service worker registered successfully:', registration); + }) + .catch(function(error) { + console.log('Service worker registration failed:', error); + }); +``` + +The `sw.js` file contains the logic for what a service worker should do. +It executes in a separate thread from the web page but provides a means +of communicating between itself and the web page via messages. + +Note that there is a scope can specify what network requests it may +intercept. + +The Vue project already has its own service worker but it is possible to +create multiple service worker files by registering them on different scopes. + +It is useful architecturally to specify a separate server worker. + +In the case of web push, the path of the scope only has reference to the domain +of the service worker and no relationship to the pathing for the web push +server. In order to specify different server workers they need to be on +different scope paths! Here's a version which can be used for testing locally. Note there can be caching issues in your browser! Incognito is highly recommended. +sw-dev.ts + self.addEventListener('push', function(event: PushEvent) { console.log('Received a push message', event);