Updates to web push guide
This commit is contained in:
77
web-push.md
77
web-push.md
@@ -1,19 +1,19 @@
|
|||||||
Web Push notifications is a web browser messaging protocol defined by the W3C.
|
Web Push notifications is a web browser messaging protocol defined by the W3C.
|
||||||
|
|
||||||
Discussions of this interesting technology are clouded because of a terminological
|
Discussions of this interesting technology are clouded because of a
|
||||||
morass.
|
terminological morass.
|
||||||
|
|
||||||
To understand how Web Push operates, we need to observe that are three (and
|
To understand how Web Push operates, we need to observe that are three (and
|
||||||
potentially four) parties involved. These are:
|
potentially four) parties involved. These are:
|
||||||
|
|
||||||
1) The user's web browser. Let's call that BROWSER
|
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
|
2) The Web Push Service Provider which is operated by the organization
|
||||||
web browser's source code. Here named PROVIDER. An example of a PROVIDER is
|
controlling the web browser's source code. Here named PROVIDER. An example of a
|
||||||
FCM (Firebase Cloud Messaging) which is owned by Google.
|
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
|
3) The Web Application that a user is visiting from their web browser. Let's
|
||||||
SERVICE (short for Web Push application service)
|
call this the SERVICE (short for Web Push application service)
|
||||||
[4) A Custom Web Push Intermediary Service, either third party or self-hosted. Called
|
[4) A Custom Web Push Intermediary Service, either third party or self-hosted.
|
||||||
INTERMEDIARY here.]
|
Called INTERMEDIARY here.]
|
||||||
|
|
||||||
The workflow works like this:
|
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
|
The SERVICE asks BROWSER for its permission to subscribe to messages coming
|
||||||
from the SERVICE.
|
from the SERVICE.
|
||||||
|
|
||||||
Provide context and obtain explicit permission before prompting for notification permission:
|
The SERVICE will provide context and obtain explicit permission before prompting
|
||||||
It is recommended to set up to a two-step opt-in process where the user is first presented
|
for notification permission:
|
||||||
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.
|
|
||||||
|
|
||||||
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<NotificationPermission> {
|
function askPermission(): Promise<NotificationPermission> {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
const permissionResult = Notification.requestPermission(function(result) {
|
const permissionResult = Notification.requestPermission(function(result) {
|
||||||
@@ -45,14 +50,54 @@ function askPermission(): Promise<NotificationPermission> {
|
|||||||
return permissionResult;
|
return permissionResult;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
If the user grants permission, the client application registers a service worker using
|
If the user grants permission, the client application registers a service worker
|
||||||
the ServiceWorkerRegistration API.
|
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.
|
||||||
|
|
||||||
|
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
|
Here's a version which can be used for testing locally. Note there can be
|
||||||
caching issues in your browser! Incognito is highly recommended.
|
caching issues in your browser! Incognito is highly recommended.
|
||||||
|
|
||||||
|
sw-dev.ts
|
||||||
|
|
||||||
self.addEventListener('push', function(event: PushEvent) {
|
self.addEventListener('push', function(event: PushEvent) {
|
||||||
console.log('Received a push message', event);
|
console.log('Received a push message', event);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user