Melhorias na dispensa de páginas em XMLHttpRequest() síncrono

Reduzir as navegações atrasadas

Joe medley
Joe Medley

É comum que uma página ou um aplicativo tenha análises ou outros dados não enviados no momento em que um usuário o fecha. Para evitar a perda de dados, alguns sites usam uma chamada síncrona para XMLHttpRequest() a fim de manter a página ou o app aberto até que os dados sejam transmitidos ao servidor. Além de maneiras melhores de salvar dados, essa técnica cria uma experiência do usuário ruim, atrasando o fechamento da página por vários segundos.

Essa prática precisa mudar, e os navegadores estão respondendo a isso. A especificação XMLHttpRequest() já está programada para descontinuação e remoção. O Chrome 80 dá o primeiro passo ao proibir chamadas síncronas em vários manipuladores de eventos, especificamente beforeunload, unload, pagehide e visibilitychange quando são disparadas na dispensa. O WebKit também recebeu recentemente uma confirmação implementando a mesma mudança de comportamento.

Neste artigo, vou descrever rapidamente as opções para quem precisa de tempo para atualizar os sites e destacar as alternativas ao XMLHttpRequest().

Recusas temporárias

O Chrome não quer apenas conectar XMLHttpRequest(), e é por isso que algumas opções temporárias de desativação estão disponíveis. Para sites na Internet, um teste de origem está disponível. Com isso, você adiciona um token específico da origem aos cabeçalhos da página que permite chamadas síncronas XMLHttpRequest(). Essa opção termina pouco antes do lançamento do Chrome 89, em março de 2021. Os clientes do Chrome Enterprise também podem usar a flag de política AllowSyncXHRInPageDismissal, que termina ao mesmo tempo.

Alternativas

Independentemente de como você envia dados de volta ao servidor, é melhor evitar esperar o descarregamento de páginas para enviar todos os dados de uma só vez. Além de criar uma experiência do usuário ruim, o descarregamento não é confiável em navegadores modernos e corre o risco de perda de dados se algo der errado. Especificamente, eventos de descarregamento geralmente não são acionados em navegadores para dispositivos móveis, porque há muitas maneiras de fechar uma guia ou um navegador nesses sistemas operacionais sem o disparo do evento unload. Com XMLHttpRequest(), o uso de payloads pequenos foi uma escolha. Agora isso é um requisito. Ambas as alternativas têm um limite de upload de 64 KB por contexto, conforme exigido pela especificação.

Buscar sinal de atividade

A API Fetch fornece uma maneira robusta de lidar com interações do servidor e uma interface consistente para uso em diferentes APIs de plataforma. Entre as opções está keepalive, que garante que uma solicitação continua independentemente de a página que a criou permanecer aberta:

window.addEventListener('unload', {
  fetch('/siteAnalytics', {
    method: 'POST',
    body: getStatistics(),
    keepalive: true
  });
}

O método fetch() tem a vantagem de ter maior controle sobre o que é enviado ao servidor. O que não é mostrado no exemplo é que fetch() também retorna uma promessa que é resolvida com um objeto Response. Como estou tentando sair do caminho de descarregamento da página, optei por não fazer nada com ela.

SendBeacon()

Na verdade, o SendBeacon() usa a API Fetch em segundo plano, e é por isso que ele tem a mesma limitação de payload de 64 KB e também garante que uma solicitação continue após o descarregamento de uma página. Sua principal vantagem é a simplicidade. Ele permite que você envie seus dados com uma única linha de código:

window.addEventListener('unload', {
  navigator.sendBeacon('/siteAnalytics', getStatistics());
}

Conclusão

Com o aumento da disponibilidade do fetch() nos navegadores, esperamos que o XMLHttpRequest() seja removido da plataforma da Web em algum momento. Os fornecedores de navegadores concordam que a remoção é necessária, mas isso levará tempo. A suspensão de uso de um dos piores casos de uso é a primeira etapa que melhora a experiência do usuário para todos.

Foto de Matthew Hamilton no Unsplash