W3docs

Push API JavaScript et Notifications

La Push API en JavaScript est un outil essentiel pour enrichir les applications web avec des notifications en temps réel, combinée aux service workers.

Introduction à la Push API en JavaScript

La Push API en JavaScript permet à une application web de recevoir des messages envoyés depuis un serveur, même lorsque la page est fermée ou que le navigateur est en arrière-plan. Elle constitue le fondement des notifications push web : alertes d'actualité, messages de discussion et rappels d'engagement qui arrivent sans que l'utilisateur ait besoin de garder un onglet ouvert.

La Push API ne fonctionne jamais seule. Elle repose sur deux autres fonctionnalités du navigateur :

  • Un service worker — un script d'arrière-plan qui reste actif après la fermeture de la page et reçoit le push.
  • La Notifications API — ce que le service worker utilise pour afficher concrètement le message à l'utilisateur.

Cette page couvre l'intégralité du flux côté client : enregistrement d'un service worker, demande de permission, abonnement avec une clé VAPID, réception du push dans le service worker et affichage d'une notification. Elle explique également le rôle de votre serveur dans ce processus.

Fonctionnement du flux push

Le chemin de bout en bout d'un seul message push ressemble à ceci :

  1. Votre page enregistre un service worker et s'abonne au push. Le navigateur renvoie un objet PushSubscription contenant une URL d'endpoint unique.
  2. Votre page envoie cet abonnement à votre serveur qui le stocke.
  3. Plus tard, votre serveur signe un message avec sa clé privée VAPID et l'envoie à l'endpoint de l'abonnement, qui appartient à un Push Service tiers (Mozilla, Google, Apple, etc.).
  4. Le Push Service réveille le navigateur de l'utilisateur et déclenche un événement push dans votre service worker.
  5. Le service worker affiche une notification en réponse.

La Push API nécessite un contexte sécurisé : la page doit être servie via HTTPS (localhost est traité comme sécurisé pour le développement). Sans cela, navigator.serviceWorker et PushManager sont indisponibles.

Mise en œuvre des notifications push

Configuration des service workers

Tout d'abord, nous devons enregistrer un service worker qui gère les tâches d'arrière-plan liées à l'envoi des notifications :

// Registering a service worker
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
        .then(function(registration) {
            console.log('Service Worker registered with scope:', registration.scope);
        }).catch(function(error) {
            console.log('Service Worker registration failed:', error);
        });
}

Demande de permission pour les notifications

Avant d'envoyer des notifications, il est nécessaire de demander la permission à l'utilisateur. La demande doit être déclenchée par un geste de l'utilisateur (comme un clic) — les navigateurs rejettent les invites de permission qui se déclenchent automatiquement au chargement de la page :

<button id="enable-notif-btn">Enable Notifications</button>
<script>
    // Asking user permission for notifications
    function requestPermission() {
        Notification.requestPermission().then(function(permission) {
            console.log('Notification permission:', permission);
        });
    }
    document.getElementById('enable-notif-btn').addEventListener('click', requestPermission);
</script>

Abonnement aux notifications push

Après avoir obtenu la permission, l'application peut s'abonner aux notifications push. La valeur applicationServerKey doit être un Uint8Array, pas la chaîne base64 que vous stockez habituellement — il faut donc la convertir en premier. VAPID (Voluntary Application Server Identification) est la paire de clés qui permet au Push Service de vérifier que les pushs proviennent bien de votre serveur : la clé publique est utilisée ici, la clé privée reste sur votre backend.

<button id="subscribe-btn">Subscribe to Push Notifications</button>
<script>
    // The VAPID public key arrives as a base64url string; the API needs a Uint8Array.
    function urlBase64ToUint8Array(base64String) {
        const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
        const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
        const raw = atob(base64);
        return Uint8Array.from([...raw].map(c => c.charCodeAt(0)));
    }

    const VAPID_PUBLIC_KEY = 'YOUR_VAPID_PUBLIC_KEY'; // base64url string from your server

    function subscribeToPush() {
        navigator.serviceWorker.ready.then(function(registration) {
            // userVisibleOnly: true is required — the browser rejects silent push subscriptions.
            return registration.pushManager.subscribe({
                userVisibleOnly: true,
                applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY)
            });
        })
        .then(function(subscription) {
            console.log('Push subscription:', JSON.stringify(subscription));
            // Send the subscription to your backend so it can push to this user later.
            return fetch('/api/save-subscription', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(subscription)
            });
        })
        .catch(function(error) {
            console.log('Failed to subscribe to push:', error);
        });
    }
    document.getElementById('subscribe-btn').addEventListener('click', subscribeToPush);
</script>

Un PushSubscription se sérialise en JSON contenant l'URL endpoint et les clés de chiffrement keys (p256dh et auth). Votre serveur a besoin de toutes ces informations pour envoyer un message. La valeur userVisibleOnly: true est obligatoire dans les navigateurs actuels : elle garantit que chaque push donnera lieu à une notification visible par l'utilisateur, c'est pourquoi les pushs silencieux en arrière-plan ne sont pas autorisés sur le web.

Gestion des messages push entrants

Pour gérer les messages entrants, le service worker écoute les événements push. La charge utile envoyée arrive sur event.data ; utilisez event.data.json() (ou .text()) pour la lire. L'encapsulation de showNotification() dans event.waitUntil() maintient le service worker actif jusqu'à ce que la notification soit affichée :

// Inside service-worker.js
self.addEventListener('push', function(event) {
    // Read the payload your server sent (fall back gracefully if there is none).
    var payload = event.data ? event.data.json() : {};

    var options = {
        body: payload.body || 'New notification.',
        icon: 'icon.png',
        vibrate: [100, 50, 100],
        data: { primaryKey: 1 }
    };

    event.waitUntil(
        self.registration.showNotification(payload.title || 'Push Notification', options)
    );
});

self.addEventListener('notificationclick', function(event) {
    event.notification.close();
    event.waitUntil(
        clients.openWindow('https://example.com')
    );
});

self.addEventListener('pushsubscriptionchange', function(event) {
    console.log('Subscription changed, re-subscribing...');
    // Re-subscribe using the same parameters
    event.registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: 'YOUR_VAPID_PUBLIC_KEY'
    }).then(function(newSubscription) {
        console.log('Re-subscribed:', newSubscription);
    }).catch(function(error) {
        console.error('Re-subscription failed:', error);
    });
});

Cet extrait présente les trois événements à gérer : push (afficher la notification), notificationclick (mettre au premier plan ou ouvrir une fenêtre lorsque l'utilisateur clique), et pushsubscriptionchange (se réabonner lorsque le navigateur fait tourner l'abonnement).

Le rôle du serveur

Le navigateur ne peut pas se pousser des messages à lui-même — chaque message provient de votre backend. Le serveur conserve la clé privée VAPID et, pour chaque abonnement stocké, envoie une requête HTTP chiffrée et signée à l'endpoint de l'abonnement. En pratique, vous utilisez une bibliothèque web-push (par exemple, web-push sur Node.js) plutôt que de construire le chiffrement manuellement :

// Server side (Node.js) — conceptual example
const webpush = require('web-push');

webpush.setVapidDetails(
    'mailto:[email protected]',
    process.env.VAPID_PUBLIC_KEY,
    process.env.VAPID_PRIVATE_KEY
);

// `subscription` is the JSON object the browser sent to /api/save-subscription
const payload = JSON.stringify({ title: 'Hello', body: 'You have a new message.' });
webpush.sendNotification(subscription, payload)
    .catch(err => console.error('Push failed:', err.statusCode));

Une réponse 410 Gone ou 404 signifie que l'abonnement a expiré — supprimez-le de votre base de données. C'est le pendant côté serveur de la gestion de pushsubscriptionchange côté client.

Bonnes pratiques pour les notifications push

  • Engagement des utilisateurs : Concevez des notifications pertinentes, ponctuelles et précises.
  • Conformité à la vie privée : Assurez-vous toujours d'obtenir le consentement de l'utilisateur avant d'envoyer des notifications.
  • Performance : Gérez la fréquence et le moment d'envoi des notifications pour éviter de saturer l'utilisateur.
  • Renouvellement des abonnements : Les abonnements push expirent périodiquement. Mettez en place une logique côté client pour vérifier l'état de l'abonnement et se réabonner si nécessaire, ou gérez les événements d'expiration depuis le service worker.

Conclusion

La Push API ouvre un canal d'interaction directe avec les utilisateurs, offrant un outil puissant pour l'engagement. En tirant parti de cette API, les développeurs peuvent offrir une expérience utilisateur plus dynamique et réactive. Une mise en œuvre correcte des notifications push peut considérablement améliorer les fonctionnalités et l'attrait des applications web, en tenant les utilisateurs informés et engagés.

Pratique

Pratique
Quelles sont les capacités et les exigences de la Push API JavaScript ?
Quelles sont les capacités et les exigences de la Push API JavaScript ?
Was this page helpful?