Push API e Notificações em JavaScript
A Push API em JavaScript é uma ferramenta essencial para desenvolvedores que desejam enriquecer aplicações web com notificações em tempo real. Esta API, combinada com
Introdução à Push API em JavaScript
A Push API em JavaScript permite que uma aplicação web receba mensagens enviadas por um servidor, mesmo quando a página está fechada ou o navegador está em segundo plano. É a base das notificações push na web: alertas de notícias, mensagens de chat e avisos de reengajamento que chegam sem o utilizador precisar manter uma aba aberta.
A Push API nunca funciona sozinha. Ela depende de outros dois recursos do navegador:
- Um service worker — um script em segundo plano que permanece ativo após o fecho da página e recebe o push.
- A Notifications API — o que o service worker usa para efetivamente exibir a mensagem ao utilizador.
Esta página abrange o fluxo completo do lado do cliente: registar um service worker, solicitar permissão, subscrever com uma chave VAPID, receber o push no service worker e exibir uma notificação. Também explica como o seu servidor se encaixa nesse processo.
Como funciona o fluxo de push
O percurso de ponta a ponta de uma única mensagem push é o seguinte:
- A sua página regista um service worker e subscreve ao push. O navegador devolve um objeto
PushSubscriptioncontendo um URL de endpoint único. - A sua página envia essa subscrição para o seu servidor e armazena-a.
- Posteriormente, o seu servidor assina uma mensagem com a sua chave privada VAPID e envia-a para o endpoint da subscrição, que pertence a um Serviço Push de fornecedor (Mozilla, Google, Apple, etc.).
- O Serviço Push acorda o navegador do utilizador e dispara um evento
pushno seu service worker. - O service worker exibe uma notificação em resposta.
A Push API requer um contexto seguro: a página deve ser servida via HTTPS (localhost é tratado como seguro para desenvolvimento). Sem isso, navigator.serviceWorker e PushManager ficam indisponíveis.
Implementar Notificações Push
Configurar Service Workers
Primeiro, precisamos de registar um service worker que lida com as tarefas em segundo plano do envio de notificações:
// 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);
});
}Solicitar Permissão para Notificações
Antes de enviar notificações, é necessário solicitar permissão ao utilizador. O pedido deve ser acionado por um gesto do utilizador (como um clique) — os navegadores rejeitam prompts de permissão que são disparados automaticamente ao carregar a página:
<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>Subscrever Notificações Push
Após obter permissão, a aplicação pode subscrever notificações push. O applicationServerKey deve ser um Uint8Array, não a string base64 que normalmente se armazena — portanto converta-o primeiro. VAPID (Voluntary Application Server Identification) é o par de chaves que permite ao Serviço Push verificar que os pushes realmente provêm do seu servidor: a chave pública vai aqui, a chave privada permanece no seu 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>Um PushSubscription serializa para JSON contendo o URL do endpoint e as keys de encriptação (p256dh e auth). O seu servidor precisa de todos estes dados para enviar uma mensagem. Definir userVisibleOnly: true é obrigatório nos navegadores atuais: promete que cada push resultará numa notificação visível ao utilizador, razão pela qual pushes silenciosos em segundo plano não são permitidos na web.
Lidar com Mensagens Push Recebidas
Para lidar com mensagens recebidas, o service worker escuta eventos push. O payload enviado chega em event.data; use event.data.json() (ou .text()) para lê-lo. Envolver showNotification() em event.waitUntil() mantém o service worker ativo até a notificação ser exibida:
// 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);
});
});Este trecho mostra os três eventos que vale a pena tratar: push (exibir a notificação), notificationclick (focar ou abrir uma janela quando o utilizador clica) e pushsubscriptionchange (rever a subscrição quando o navegador a renova).
O Papel do Servidor
O navegador não pode enviar push para si mesmo — cada mensagem origina-se no seu backend. O servidor mantém a chave privada VAPID e, para cada subscrição armazenada, envia um pedido HTTP encriptado e assinado para o endpoint da subscrição. Na prática, utiliza-se uma biblioteca de web-push (por exemplo, web-push no Node.js) em vez de construir a encriptação manualmente:
// 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));Uma resposta 410 Gone ou 404 significa que a subscrição expirou — elimine-a da sua base de dados. Este é o contraponto do lado do servidor para tratar pushsubscriptionchange no cliente.
Boas Práticas para Notificações Push
- Envolvimento do Utilizador: Conceba notificações que sejam oportunas, relevantes e precisas.
- Conformidade com a Privacidade: Garanta sempre que o consentimento do utilizador é obtido antes de enviar notificações.
- Desempenho: Gira a frequência e o momento das notificações para evitar sobrecarregar o utilizador.
- Renovação de Subscrição: As subscrições push expiram periodicamente. Implemente lógica do lado do cliente para verificar o estado da subscrição e rever quando necessário, ou trate eventos de expiração provenientes do service worker.
Conclusão
A Push API abre um canal de interação direta com os utilizadores, fornecendo uma ferramenta poderosa para o envolvimento. Ao aproveitar esta API, os desenvolvedores podem oferecer uma experiência de utilizador mais dinâmica e responsiva. A implementação correta de notificações push pode melhorar significativamente a funcionalidade e o apelo das aplicações web, mantendo os utilizadores informados e envolvidos.