Como o JavaScript funciona: a mecânica das notificações por push na Web

Este é o post #9 da série dedicada a explorar JavaScript e seus componentes de construção. No processo de identificação e descrição dos elementos centrais, também compartilhamos algumas regras práticas que usamos ao criar o SessionStack , um aplicativo JavaScript leve que precisa ser robusto e altamente eficiente para ajudar os usuários a ver e reproduzir seus defeitos de aplicativos da Web em tempo real. .

Abaixo estão os posts dessa série publicados até o momento

Hoje voltamos nossa atenção para notificações por push da Web: veremos os componentes de construção, exploraremos os processos por trás do envio/recebimento de notificações e, no final, compartilharemos como planejamos usá -los para criar uma nova funcionalidade do produto.

As notificações por push são muito comuns no mundo dos dispositivos móveis. Por um motivo ou outro, eles fizeram sua entrada na web muito tarde, embora tenha sido um recurso altamente solicitado pelos desenvolvedores.

Visão geral

As notificações por push da Web permitem que os usuários optem por atualizações oportunas de aplicativos da web que visam engajar novamente a base de usuários com conteúdo que pode ser interessante, importante e oportuno para os usuários.

O push é baseado em Service Workers, que discutimos em detalhes em um post anterior .

A razão para empregar trabalhadores do serviço, neste caso, é porque eles operam em segundo plano. Isso é ótimo para notificações push porque significa que o código está sendo executado apenas quando um usuário interage com a notificação em si.

Push & notificação

Push e notificação são duas APIs diferentes.

  • Push — é invocado quando o servidor fornece informações a um Service Worker.
  • Notificação — esta é a ação de um Service Worker ou um script em um aplicativo da web que mostra informações para o usuário.

Push (Empurrar)

Existem três etapas gerais para implementar um push:

  1. A interface do usuário — adicionando a lógica do lado do cliente necessária para inscrever um usuário em um push. Essa é a lógica JavaScript de que a interface do seu aplicativo da web precisa para permitir que o usuário se registre para enviar mensagens.
  2. Enviando a mensagem push — implementando a chamada da API no seu servidor que aciona uma mensagem push para o dispositivo do usuário.
  3. Recebendo a mensagem de envio — manipulando a mensagem de envio quando ela chega no navegador.

Agora vamos descrever todo o processo em mais detalhes.

Detecção de suporte ao navegador

Primeiro, precisamos verificar se o navegador atual suporta envio de mensagens. Podemos verificar se o push é suportado por duas verificações simples:

  1. Verificar serviceWorker no objeto do navigator
  2. Verifique o PushManager no objeto da window

Ambas as verificações são assim:

Registrar um Service Worker

Neste ponto, sabemos que o recurso é suportado. O próximo passo é registrar nosso Service Worker.

Registrar um Service Worker é algo com o qual você já deve estar familiarizado em uma postagem anterior da nossa.

Solicitando permissão

Depois que um Service Worker for registrado, poderemos continuar assinando o usuário. Para fazer isso, precisamos obter permissão para enviar mensagens de push.

A API para obter permissão é relativamente simples, mas a desvantagem é que a API mudou de um retorno de chamada para um Promise . Isso apresenta um problema: não podemos dizer qual versão da API foi implementada pelo navegador atual, então você precisa implementar e manipular ambos.

Parece algo como isto:

A chamada Notification.requestPermission() exibirá o seguinte aviso para o usuário:

Quando a permissão for concedida, fechada ou bloqueada, receberemos o resultado como uma string: 'granted' , 'default' ou 'denied' .

Lembre-se de que, se o usuário clicar no botão Block , seu aplicativo da Web não poderá solicitar permissão ao usuário até que ele "desbloqueie" o aplicativo manualmente alterando o estado da permissão. Esta opção está enterrada no painel de configurações.

Inscrevendo um usuário no PushManager

Assim que tivermos o nosso Service Worker registrado e tivermos permissão, podemos inscrever um usuário chamando registration.pushManager.subscribe() quando você registrar seu Service Worker.

O snippet inteiro pode ter esta aparência (incluindo o registro do Service Worker):

O registration.pushManager.subscribe(options) usa um objeto de opções , que consiste em parâmetros obrigatórios e opcionais:

  • userVisibleOnly : Um booleano que indica que a assinatura de push retornada será usada apenas para mensagens cujo efeito é tornado visível para o usuário. Tem que ser definido para true caso contrário, você receberá um erro (há razões históricas para isso).
  • applicationServerKey : Um DOMString ou ArrayBuffer codificado em Base64 contendo uma chave pública que o servidor de envio utilizará para autenticar seu servidor de aplicativos.

Seu servidor precisa gerar um par de chaves do servidor de aplicativos — elas também são conhecidas como chaves VAPID, exclusivas do servidor. Eles são um par de chave pública e privada. A chave privada é secretamente armazenada no seu final, enquanto a pública é trocada com o cliente. As chaves permitem que um serviço de envio saiba qual servidor de aplicativos assinou um usuário e garante que ele seja o mesmo servidor que aciona as mensagens de envio para esse usuário específico.

Você precisa criar o par de chaves privada/pública apenas uma vez para o seu aplicativo. Uma maneira de fazer isso é https://web-push-codelab.glitch.me/ .

O navegador passa o applicationServerKey (o public) para um serviço de push ao inscrever o usuário, o que significa que o serviço de push pode vincular a chave pública do seu aplicativo ao PushSubscription do usuário.

Isto é o que acontece:

  • Seu aplicativo da web é carregado e você chama subscribe() , passando sua chave de servidor.
  • O navegador faz uma solicitação de rede a um serviço de push que gerará um nó de extremidade, associará esse nó de extremidade à chave e retornará o nó de extremidade ao navegador.
  • O navegador adicionará esse terminal ao objeto PushSubscription , que é retornado por meio da promessa subscribe() .

Posteriormente, sempre que você quiser enviar uma mensagem push, será necessário criar um cabeçalho de autorização que contenha informações assinadas com a chave privada do seu servidor de aplicativos. Quando o serviço push recebe uma solicitação para enviar uma mensagem push, ele validará o cabeçalho procurando a chave pública que já está vinculada a esse endpoint específico (a segunda etapa).

O objeto PushSubscription

Um PushSubscription contém todas as informações necessárias para enviar uma mensagem push para o dispositivo do usuário. É assim que parece:

{ 
"endpoint": "https://domain.pushservice.com/some-id",
"keys": {
"p256dh": "BIPUL12DLfytvTajnryr3PJdAgXS3HGMlLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WArAPIxr4gK0_dQds4yiI=",
"auth":"FPssMOQPmLmXWmdSTdbKVw=="
}
}

O endpoint é o URL dos serviços push. Para acionar uma mensagem push, faça uma solicitação POST para esse URL.

O objeto de keys contém os valores usados ​​para criptografar os dados da mensagem enviados com uma mensagem push.

Depois que um usuário é inscrito e você tem um PushSubscription é necessário enviá-lo ao seu servidor. Lá (no servidor) você salvará a assinatura em um banco de dados e a partir de agora a usará para enviar mensagens push para esse usuário.

Enviando a mensagem push

Quando você quiser enviar uma mensagem push para seus usuários, a primeira coisa que você precisa é de um serviço push. Você está dizendo ao serviço de push (via chamada de API) quais dados enviar, quem enviar a mensagem e quais os critérios sobre como enviar a mensagem. Normalmente, essa chamada da API é feita no seu servidor.

Serviços push

Um serviço push é aquele que recebe solicitações, valida-as e envia a mensagem push para o navegador adequado.

Observe que o serviço push não é gerenciado por você — é um serviço de terceiros. Seu servidor é aquele que se comunica com o serviço push por meio de uma API. Um exemplo de serviço de envio é o FCM do Google .

O serviço de push lida com todo o trabalho pesado. Por exemplo, se o navegador estiver off-line, o serviço de push colocará as mensagens na fila e aguardará até que o navegador fique on-line novamente, antes de enviar a respectiva mensagem.

Cada navegador pode usar qualquer serviço de push desejado e isso é algo que está além do controle do desenvolvedor.

Todos os serviços push, no entanto, possuem as mesmas APIs, portanto, isso não cria dificuldades de implementação.

Para obter a URL que manipulará as solicitações para suas mensagens push, você precisará verificar o valor armazenado do endpoint no objeto PushSubscription .

API de serviço push

O Push Service API fornece uma maneira de enviar mensagens para um usuário. A API é o Web Push Protocol, que é um padrão IETF que define como você faz uma chamada de API para um serviço de push.

Os dados que você envia com uma mensagem push devem ser criptografados. Dessa forma, você evita que os serviços de push possam exibir os dados enviados. Isso é importante porque o navegador é aquele que decide qual serviço de envio usar (e pode estar usando algum serviço de envio não confiável e não seguro o suficiente).

Para cada mensagem de envio, você também pode fornecer as seguintes instruções:

  • TTL — define por quanto tempo uma mensagem deve ser enfileirada antes de ser removida e não entregue.
  • Prioridade — define a prioridade de cada mensagem, que permite que o serviço de envio envie apenas as de alta prioridade, caso a duração da bateria do dispositivo do usuário tenha que ser preservada.
  • Tópico — fornece uma mensagem push a um nome de tópico que substituirá mensagens pendentes com o mesmo tópico, para que, quando o dispositivo estiver ativo, o usuário não receba informações desatualizadas.

Empurrar evento no navegador

Depois de enviar a mensagem para o serviço de push, conforme explicado acima, a mensagem estará em um estado pendente até que uma das seguintes situações aconteça:

  • O dispositivo fica online.
  • A mensagem expira na fila devido ao TTL.

Quando o serviço de envio envia uma mensagem, o navegador irá recebê-lo, descriptografá-lo e despachar um evento push em seu Service Worker.

O melhor de tudo é que o navegador pode executar seu Service Worker mesmo quando sua página da web não estiver aberta. O seguinte acontece:

  • A mensagem push chega ao navegador, que descriptografa
  • O navegador acorda o trabalhador de serviço
  • Um evento push é enviado para o Service Worker

O código para configurar um ouvinte de evento de envio deve ser bem parecido com qualquer outro ouvinte de evento que você escreveria em JavaScript:

Uma das coisas a se entender sobre os Trabalhadores do Serviço é que você tem pouco controle sobre o tempo que o código do service worker será executado. O navegador decide quando acordá-lo e quando finalizá-lo.

Em Service Workers, event.waitUntil(promise) informa ao navegador que o trabalho está em andamento até que a promessa seja resolvida e ele não deve finalizar o service worker se desejar que o trabalho seja concluído.

Aqui está um exemplo de como manipular o evento push :

Chamar self.registration.showNotification() exibe uma notificação para o usuário e retorna uma promessa que será resolvida assim que a notificação for exibida.

O showNotification(title, options) pode ser visualmente ajustado para atender às suas necessidades. O parâmetro title é uma string enquanto options é um objeto assim:

{ 
"//": "Visual Options",
"body": "<String>",
"icon": "<URL String>",
"image": "<URL String>",
"badge": "<URL String>",
"vibrate": "<Array of Integers>",
"sound": "<URL String>",
"dir": "<String of 'auto' | 'ltr' | 'rtl'>",

"//": "Behavioural Options",
"tag": "<String>",
"data": "<Anything>",
"requireInteraction": "<boolean>",
"renotify": "<Boolean>",
"silent": "<Boolean>",

"//": "Both Visual & Behavioural Options",
"actions": "<Array of Strings>",

"//": "Information Option. No visual affect.",
"timestamp": "<Long>"
}

Você pode ler com mais detalhes o que cada opção faz aqui — https://developer.mozilla.org/pt-BR/docs/Web/API/ServiceWorkerRegistration/showNotification .

As notificações por push podem ser uma ótima maneira de chamar a atenção dos usuários sempre que houver informações urgentes, importantes e urgentes que você queira compartilhar com elas.

Nós da SessionStack, por exemplo, planejamos utilizar notificações push para informar nossos usuários quando houver uma falha, problema ou anomalia em seus produtos. Isso permitirá que nossos usuários saibam imediatamente que há algo errado acontecendo. Em seguida, eles podem reproduzir o problema como um vídeo e ver tudo o que aconteceu com o usuário final aproveitando os dados coletados por nossa biblioteca, como alterações do DOM, interações do usuário, solicitações de rede, exceções não tratadas e mensagens de depuração.

Esse recurso não apenas ajudará nossos usuários a entender e reproduzir qualquer problema, mas também permitirá que os clientes sejam alertados assim que isso acontecer.

Existe um plano gratuito se você quiser experimentar o SessionStack .

Referências

Este é um artigo traduzido com a autorização do autor. O artigo original pode ser lido em https://blog.sessionstack.com/how-javascript-works-the-mechanics-of-web-push-notifications-290176c5c55d

Autor do post original — Alexander Zlatkov— Co-founder & CEO @SessionStack