Comment gérer les notifications Web Push dans les sites Web et les PWA –
Les notifications push sont monnaie courante sur le Web moderne. Ils vous permettent de communiquer des informations en temps opportun à l’utilisateur, même si votre site n’est pas réellement ouvert. Le navigateur de l’utilisateur gère les événements push entrants et affiche les notifications à l’aide de surfaces d’interface utilisateur système telles que Windows Action Center et Android lockscreen.
La mise en œuvre de Web Push dans votre site ou PWA nécessite la combinaison de deux API de navigateur distinctes. Le code responsable de l’abonnement et de la réception des notifications utilise le composant Push API des service workers. Ce code s’exécute continuellement en arrière-plan et sera invoqué par le navigateur lorsqu’une nouvelle notification doit être traitée.
Lorsqu’un événement est reçu, le service worker doit utiliser l’API de notification pour afficher réellement la notification. Cela crée une alerte visuelle via des interfaces au niveau du système d’exploitation.
Voici un guide complet pour faire fonctionner Web Push sur votre site. Nous supposerons que vous avez déjà un composant côté serveur qui peut enregistrer des abonnements push et envoyer vos alertes.
Sommaire
Le travailleur de service
Commençons par le travailleur de service. Les techniciens de maintenance ont plusieurs rôles : ils peuvent mettre en cache les données pour une utilisation hors ligne, exécuter des synchronisations périodiques en arrière-plan et agir en tant que gestionnaires de notifications. Les techniciens de maintenance utilisent une architecture événementielle. Une fois enregistré par un site, le navigateur de l’utilisateur invoquera le service worker en arrière-plan lorsque des événements auxquels il s’abonne sont générés.
Pour Web Push, un événement principal est nécessaire : push
. Celui-ci reçoit un PushEvent
objet qui vous permet d’accéder à la charge utile poussée depuis le serveur.
self.addEventListener("push", e => { const payload = JSON.parse(e.data.text()); e.waitUntil(self.registration.showNotification( payload.title, { body: payload.body, icon: "/icon.png" } )); });
Le code ci-dessus configure un service worker capable de réagir aux événements push entrants. Il s’attend à ce que le serveur envoie des charges utiles JSON ressemblant à ceci :
{ "title": "Title text for the notification", "body": "This is the longer text of the notification." }
Lorsqu’un événement push est reçu, le technicien de maintenance affiche une notification de navigateur en appelant le showNotification()
fonction disponible sur son self.registration
biens. La fonction est enveloppée dans un waitUntil()
appelez afin que le navigateur attende que la notification s’affiche avant de mettre fin au service worker.
Le showNotification()
La fonction prend deux arguments : le texte du titre de la notification et un objet d’options. Deux options sont transmises dans cet exemple, un corps de texte plus long et une icône à afficher dans la notification. De nombreuses autres options sont disponibles pour vous permettre de configurer des modèles de vibration, des badges personnalisés et des exigences d’interaction. Tous les navigateurs et systèmes d’exploitation ne prennent pas en charge toutes les fonctionnalités exposées par l’API.
Complétez le côté service worker du code en le réenregistrant dans votre code JavaScript principal :
if (navigator.serviceWorker) { // replace with the path to your service worker file navigator.serviceWorker.register("/sw.js").catch(() => { console.error("Couldn't register the service worker.") }); }
Ce code doit s’exécuter à chaque chargement de page. Il s’assure que le navigateur prend en charge les techniciens de maintenance, puis enregistre le fichier de travail. Les navigateurs mettront automatiquement à jour le service worker chaque fois que la copie du serveur présente des différences d’octets par rapport à la version actuellement installée.
Inscription aux abonnements Push
Vous devez maintenant abonner le navigateur aux notifications push. Le code suivant appartient à votre fichier JavaScript principal, en dehors du service worker.
async function subscribeToPush() { if (navigator.serviceWorker) { const reg = await navigator.serviceWorker.getRegistration(); if (reg && reg.pushManager) { const subscription = await reg.pushManager.getSubscription(); if (!subscription) { const key = await fetch("https://example.com/vapid_key"); const keyData = await key.text(); const sub = await reg.pushManager.subscribe({ applicationServerKey: keyData, userVisibleOnly: true }); await fetch("https://example.com/push_subscribe", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({ endpoint: sub.endpoint, expirationTime: sub.expirationTime, keys: sub.toJSON().keys }) }); } } } }
Appelez ensuite votre fonction pour abonner le navigateur aux notifications push :
Voyons ce que fait le code d’abonnement. Les premières lignes vérifient la présence d’un service worker, récupèrent son enregistrement et détectent la prise en charge des notifications push. pushManager
ne sera pas défini dans les navigateurs qui ne prennent pas en charge Web Push.
Appel pushManager.getSubscription()
renvoie une promesse qui se résout en un objet décrivant l’abonnement push actuel du navigateur pour votre site. Si cela est déjà défini, nous n’avons pas besoin de réinscrire l’utilisateur.
Le véritable flux d’abonnement commence par la demande d’extraction des clés VAPID du serveur. La spécification VAPID est un mécanisme qui permet au navigateur de vérifier que les événements push proviennent réellement de votre serveur. Vous devez exposer un point de terminaison d’API de serveur qui fournit une clé VAPID. Celui-ci est remis au pushManager.subscribe()
fonction afin que le navigateur connaisse la clé de confiance. Le séparé userVisibleOnly
L’option indique que nous n’afficherons que les notifications qui s’afficheront visiblement à l’écran.
Le pushManager.subscribe()
l’appel renvoie un PushSubscription
objet décrivant votre nouvel abonnement. Ces données sont envoyées au serveur dans une autre requête d’extraction. Dans une vraie application, vous enverriez également l’ID de l’utilisateur actif afin de pouvoir lier l’abonnement push à son appareil.
Votre code côté serveur pour envoyer une notification push à un utilisateur devrait ressembler à ceci :
- Interrogez votre magasin de données pour tous les abonnements push liés à l’utilisateur cible.
- Envoyez votre charge utile de notification au point de terminaison indiqué par chaque abonnement, en veillant à inclure les clés d’authentification de l’abonnement (
keys
dans les données envoyées par le navigateur lors de la souscription). Signez l’événement avec la même clé VAPID que vous avez envoyée au navigateur.
Chaque abonnement est endpoint
référencera la plate-forme de livraison de notification du fournisseur de navigateur. Cette URL comprend déjà un identifiant unique pour l’abonnement. Lorsque vous envoyez une charge utile au point de terminaison, le processus d’arrière-plan du navigateur finira par recevoir les données et appeler votre service worker. Pour Chrome sur Android, le processus du navigateur est directement intégré au démon de notification système.
Quand inscrire l’utilisateur ?
Lors de la configuration des flux d’abonnement, n’oubliez pas que l’utilisateur devra accuser réception d’une invite d’autorisation du navigateur avant la fin de l’enregistrement. De nombreux navigateurs masquent ou rejettent automatiquement les demandes d’autorisation non sollicitées ; dans tous les cas, demander à un utilisateur de s’abonner au moment où il atterrit sur votre site peut ne pas donner le résultat souhaité.
Vous obtenez les meilleures chances de réussite de l’inscription en couplant les demandes d’abonnement à une action directe de l’utilisateur. Envisagez de fournir une bannière dans l’application qui explique les avantages de l’activation des notifications et propose un bouton « Activer maintenant ». Vous pouvez vérifier si l’utilisateur est déjà abonné et masquer la bannière avec le pushManager.getSubscription()
fonction illustrée ci-dessus.
Cliquer sur le bouton d’activation devrait appeler votre fonction d’abonnement. Le processus peut prendre quelques secondes pendant que le navigateur configure l’enregistrement et que vos appels réseau se terminent. L’affichage d’un spinner de chargement pendant ce temps aidera à tenir l’utilisateur informé.
Les utilisateurs doivent également disposer d’un moyen de se désinscrire. Bien qu’ils puissent révoquer l’autorisation du navigateur à tout moment, certains utilisateurs rechercheront une option dans l’application, surtout s’ils ont installé votre site en tant que PWA.
Voici une implémentation de désabonnement simple :
async function unsubscribePush() { const reg = await navigator.serviceWorker.getRegistration(); const subscription = await reg.pushManager.getSubscription(); if (subscription) { await subscription.unsubscribe(); await fetch(`https://example.com/push_unsubscribe/${subscription.endpoint}`, {method: "DELETE"}); } else { // already subscribed } }
Appel unsubscribe()
sur un PushSubscription
annule l’abonnement, ramenant le navigateur à son état par défaut. Votre agent de service cessera de recevoir push
événements. Le point de terminaison de l’abonnement est envoyé à votre serveur afin que vous puissiez le supprimer de votre magasin de données et éviter d’envoyer des données vers ce qui est maintenant une URL morte.
Gestion des expirations et des renouvellements
Vous avez peut-être remarqué le expirationTime
propriété sur le PushSubscription
objet créé par le navigateur. Cela ne sera pas toujours défini ; quand c’est le cas, l’appareil cessera de recevoir des notifications après ce délai.
En pratique, expirationTime
n’est actuellement pas utilisé dans les principaux navigateurs. Les jetons produits par Chrome n’expirent qu’une fois désabonnés manuellement. expirationTime
est toujours null
. Firefox ne définit pas expirationTime
soit mais son service de notification peut remplacer les abonnements pendant leur durée de vie.
Vous pouvez répondre au navigateur qui modifie votre abonnement push actif en implémentant le pushsubscriptionchange
événement dans votre travailleur de service. Malheureusement, il existe deux versions de cet événement : l’implémentation d’origine, actuellement utilisée par Firefox, et la nouvelle v2, qui n’est encore prise en charge par aucun navigateur.
La spécification d’origine présente de sérieux problèmes d’utilisation qui rendent difficile la réponse à l’événement. Lorsque vous recevez un événement v1, le navigateur a supprimé l’abonnement d’origine et vous devez en créer un nouveau manuellement. Le problème est que sans accès à l’abonnement expiré, vous ne pouvez pas envoyer de demande de « remplacer » à votre serveur – vous n’avez aucun moyen d’accéder à l’ancien endpoint
URL.
La spécification v2 résout ce problème en fournissant un événement avec oldSubscription
et newSubscription
Propriétés. Lorsque vous recevez l’événement, l’ancien abonnement a été annulé mais vous pouvez toujours accéder à ses propriétés. Le nouvel abonnement est maintenant créé pour vous par le navigateur.
Voici un exemple de mise en œuvre pushsubscriptionchange
avec la nouvelle spécification :
self.addEventListener("pushsubscriptionchange", e => { e.waitUntil(async () => { await fetch("https://example.com/push_change", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ auth: (e.newSubscription.toJSON().keys?.auth || null), endpoint: e.newSubscription.endpoint, endpointOld: e.oldSubscription.endpoint, expirationTime: e.newSubscription.expirationTime, p256dh: (e.newSubscription.toJSON().keys?.p256dh || null) }) }); }); });
Les points de terminaison sont uniques afin que votre serveur puisse rechercher l’ancien abonnement et mettre à jour ses propriétés avec celles du nouvel abonnement. Si vous souhaitez également ajouter la prise en charge de l’ancienne spécification, vous devrez suivre manuellement le point de terminaison d’abonnement actif en dehors de l’API push. Le stocker dans localStorage
ou IndexedDB vous permettra d’y accéder dans votre pushsubscriptionchange
gestionnaire afin que vous puissiez demander au serveur de remplacer l’abonnement.
La spécification révisée est beaucoup plus facile à mettre en œuvre que son homologue plus ancienne. Même s’il n’est pas encore pris en charge dans les navigateurs, cela vaut quand même la peine de l’ajouter à votre service worker. Quelques lignes de code assureront la pérennité de votre traitement push contre les nouvelles versions du navigateur.
Ajout de boutons d’action
Les notifications push peuvent inclure des boutons interactifs qui permettent à l’utilisateur de prendre des mesures immédiates. Voici un showNotification()
appel qui en crée un :
self.registration.showNotification( "Notification with actions", { body: "This notification has a button.", actions: [ { action: "/home", title: "Go to Homescreen", icon: "/home.png" } ] } );
Chaque notification peut inclure plusieurs actions, chacune avec une étiquette, une icône et action
. Cette dernière propriété doit identifier une action que votre application peut lancer en réponse à la pression de l’utilisateur.
Lorsque l’utilisateur appuie sur une action, votre technicien de maintenance reçoit un notificationclick
un événement:
self.addEventListener("notificationclick", e => { const uri = e.action; const notification = e.notification; notification.close(); clients.openWindow(`${self.location.origin}${action}`); });
Nous utilisons le action
propriété pour déclarer un URI vers lequel l’utilisateur peut naviguer. Un nouvel onglet s’ouvre sur l’URI lorsque la notification est enfoncée. Appel notification.close()
garantit que la notification est également rejetée. Sinon, certaines plates-formes obligeront l’utilisateur à le faire glisser manuellement.
Résumé
La mise en œuvre de Web Push peut sembler intimidante si vous n’avez jamais travaillé avec les API pertinentes auparavant. Plus que les préoccupations techniques, vous devez garder l’expérience utilisateur au premier plan de votre esprit et vous assurer de communiquer Pourquoi cela vaut la peine d’activer les notifications.
L’abonnement et la désabonnement au push se produisent dans le code JavaScript principal de votre application, en utilisant navigator.serviceWorker
Apis. Le code qui répond aux nouveaux événements push et affiche les notifications du navigateur réside dans le service worker lui-même.
Web Push est désormais pris en charge par la plupart des principaux navigateurs Web, Safari étant la principale exception. N’oubliez pas que les notifications s’afficheront différemment dans chaque famille de navigateurs et de systèmes d’exploitation. Par conséquent, ne supposez pas qu’une fonctionnalité particulière du showNotification()
L’API sera universellement disponible.