Como oferecer aplicativos rápidos e leves com o Save-Data

O cabeçalho de solicitação de dicas de cliente HTTP Save-Data, disponível nos navegadores Chrome, Opera e Yandex, permite que os desenvolvedores ofereçam aplicativos mais leves e rápidos aos usuários que ativam o Modo economia de dados no navegador.

A necessidade de páginas leves

Estatísticas do Web Light

Todos concordam que páginas da Web mais rápidas e leves proporcionam uma experiência do usuário mais satisfatória, permitem uma melhor compreensão e retenção de conteúdo e geram mais conversões e receita. Pesquisas do Google mostraram que "…o carregamento de páginas otimizadas é quatro vezes mais rápido do que o da página original e usa 80% menos bytes. Como o carregamento dessas páginas é muito mais rápido, também observamos um aumento de 50% no tráfego para elas.

E, embora o número de conexões 2G esteja finalmente em declínio, o 2G ainda era a tecnologia de rede dominante em 2015. A penetração e a disponibilidade das redes 3G e 4G estão crescendo rapidamente, mas os custos de propriedade associados e as restrições de rede ainda são um fator significativo para centenas de milhões de usuários.

Esses são argumentos fortes para a otimização de páginas.

Há métodos alternativos para melhorar a velocidade do site sem o envolvimento direto do desenvolvedor, como navegadores proxy e serviços de transcodificação. Embora esses serviços sejam bastante conhecidos, eles têm desvantagens significativas: compactação simples (e às vezes inaceitável) de imagens e textos, incapacidade de processar páginas seguras (HTTPS), otimização apenas de páginas visitadas por um resultado da pesquisa e muito mais. A própria popularidade desses serviços é um indicador de que os desenvolvedores da Web não estão atendendo adequadamente à alta demanda dos usuários por aplicativos e páginas rápidos e leves. Mas alcançar essa meta é um caminho complexo e, às vezes, difícil.

O cabeçalho da solicitação Save-Data

Uma técnica bastante simples é deixar o navegador ajudar, usando o cabeçalho da solicitação Save-Data. Ao identificar esse cabeçalho, uma página da Web pode personalizar e oferecer uma experiência do usuário otimizada para usuários com restrições de custo e desempenho.

Os navegadores compatíveis (abaixo) permitem que o usuário ative um *Modo economia de dados* que concede ao navegador permissão para aplicar um conjunto de otimizações para reduzir a quantidade de dados necessária para renderizar a página. Quando esse recurso é exposto ou anunciado, o navegador pode solicitar imagens de resolução mais baixa, adiar o carregamento de alguns recursos ou rotear solicitações por um serviço que aplica outras otimizações específicas de conteúdo, como compactação de recursos de imagem e texto.

Suporte ao navegador

  • O Chrome 49+ anuncia Save-Data quando o usuário ativa a opção "Economia de dados" em dispositivos móveis ou a extensão "Economia de dados" em navegadores para computador.
  • O Opera 35+ anuncia Save-Data quando o usuário ativa o modo "Opera Turbo" no computador ou a opção "Economia de dados" em navegadores Android.
  • O Yandex 16.2+ anuncia Save-Data quando o modo Turbo está ativado em navegadores para computadores ou dispositivos móveis.

Como detectar a configuração Save-Data

Para determinar quando oferecer a experiência "light" aos usuários, seu aplicativo pode verificar o cabeçalho da solicitação de dicas de cliente HTTP Save-Data. Esse cabeçalho da solicitação indica a preferência do cliente por um uso reduzido de dados devido a altos custos de transferência, velocidades de conexão lentas ou outros motivos.

Quando o usuário ativa o modo de economia de dados no navegador, o navegador anexa o cabeçalho da solicitação Save-Data a todas as solicitações de saída (HTTP e HTTPS). Até o momento, o navegador anuncia apenas um token *on no cabeçalho (Save-Data: on), mas isso pode ser estendido no futuro para indicar outras preferências do usuário.

Além disso, é possível detectar se Save-Data está ativado no JavaScript:

if ('connection' in navigator) {
  if (navigator.connection.saveData === true) {
    // Implement data saving operations here.
  }
}

Verificar a presença do objeto connection no objeto navigator é fundamental, porque ele representa a API Network Information, que é implementada apenas nos navegadores da internet Google Chrome, Google Chrome para Android e Samsung Internet. A partir daí, você só precisa verificar se navigator.connection.saveData é igual a true e implementar as operações de salvamento de dados nessa condição.

O
cabeçalho Save-Data revelado nas Ferramentas para Desenvolvedores do Chrome, mostrado junto com a
extensão Economia de Dados.
Ativar a extensão Economia de dados no Chrome para computador.

Se o aplicativo usar um service worker, ele poderá inspecionar os cabeçalhos da solicitação e aplicar a lógica relevante para otimizar a experiência. Como alternativa, o servidor pode procurar as preferências anunciadas no cabeçalho da solicitação Save-Data e retornar uma resposta alternativa, como marcação diferente, imagens e vídeos menores etc.

Dicas de implementação e práticas recomendadas

  1. Ao usar Save-Data, forneça alguns dispositivos de interface que ofereçam suporte a ele e permitam que os usuários alternem facilmente entre as experiências. Por exemplo:
    • Notifique os usuários de que o Save-Data é compatível e incentive o uso dele.
    • Permita que os usuários identifiquem e escolham o modo com comandos adequados e botões de ativação/desativação ou caixas de seleção intuitivos.
    • Quando o modo de economia de dados estiver selecionado, anuncie e ofereça uma maneira fácil e óbvia de desativá-lo e voltar à experiência completa, se desejado.
  2. Lembre-se de que aplicativos leves não são inferiores. Eles não omitem funcionalidades ou dados importantes, apenas estão mais conscientes dos custos envolvidos e da experiência do usuário. Exemplo:
    • Um aplicativo de galeria de fotos pode oferecer prévias de resolução mais baixa ou usar um mecanismo de carrossel com menos código.
    • Um aplicativo de pesquisa pode retornar menos resultados por vez, limitar o número de resultados com muita mídia ou reduzir o número de dependências necessárias para renderizar a página.
    • Um site de notícias pode mostrar menos matérias, omitir categorias menos populares ou fornecer prévias de mídia menores.
  3. Forneça uma lógica de servidor para verificar o cabeçalho da solicitação Save-Data e considere fornecer uma resposta de página alternativa e mais leve quando ele estiver ativado. Por exemplo, reduza o número de recursos e dependências necessários, aplique uma compactação de recursos mais agressiva etc.
    • Se você estiver veiculando uma resposta alternativa com base no cabeçalho Save-Data, lembre-se de adicioná-lo à lista Vary (Vary: Save-Data) para informar aos caches upstream que eles devem armazenar em cache e veicular essa versão somente se o cabeçalho da solicitação Save-Data estiver presente. Para mais detalhes, consulte as práticas recomendadas para interação com caches.
  4. Se você usa um service worker, seu aplicativo pode detectar quando a opção de economia de dados está ativada verificando a presença do cabeçalho de solicitação Save-Data ou o valor da propriedade navigator.connection.saveData. Se estiver ativada, considere se é possível reescrever a solicitação para buscar menos bytes ou usar uma resposta já buscada.
  5. Considere aumentar Save-Data com outros indicadores, como informações sobre o tipo de conexão e a tecnologia do usuário (consulte a API NetInfo). Por exemplo, talvez você queira exibir a experiência leve para qualquer usuário em uma conexão 2G, mesmo que Save-Data não esteja ativado. Por outro lado, só porque o usuário está em uma conexão 4G "rápida", não significa que ele não esteja interessado em economizar dados, por exemplo, em roaming. Além disso, você pode aumentar a presença de Save-Data com a dica de cliente HTTP Device-Memory para se adaptar ainda mais aos usuários em dispositivos com memória limitada. A memória do dispositivo do usuário também é anunciada na dica de cliente HTTP navigator.deviceMemory.

Receitas

O que você pode alcançar com o Save-Data é limitado apenas pelo que você pode criar. Para dar uma ideia do que é possível, vamos analisar alguns casos de uso. Você pode pensar em outros casos de uso ao ler este artigo. Sinta-se à vontade para testar e ver o que é possível fazer.

Como verificar se há Save-Data no código do lado do servidor

Embora o estado Save-Data seja algo que você pode detectar em JavaScript usando a propriedade navigator.connection.saveData, às vezes é preferível detectá-lo no lado do servidor. O JavaScript pode não ser executado em alguns casos. Além disso, a detecção do lado do servidor é a única maneira de modificar a marcação antes de ser enviada ao cliente, o que está envolvido em alguns dos casos de uso mais benéficos do Save-Data.

A sintaxe específica para detectar o cabeçalho Save-Data no código do lado do servidor depende da linguagem usada, mas a ideia básica é a mesma para qualquer back-end de aplicativo. No PHP, por exemplo, os cabeçalhos da solicitação são armazenados na matriz superglobal $_SERVER em índices que começam com HTTP_. Isso significa que é possível detectar o cabeçalho Save-Data verificando a existência e o valor da variável $_SERVER["HTTP_SAVE_DATA"], da seguinte maneira:

// false by default.
$saveData = false;

// Check if the `Save-Data` header exists and is set to a value of "on".
if (isset($_SERVER["HTTP_SAVE_DATA"]) && strtolower($_SERVER["HTTP_SAVE_DATA"]) === "on") {
  // `Save-Data` detected!
  $saveData = true;
}

Se você colocar essa verificação antes que qualquer marcação seja enviada ao cliente, a variável $saveData vai conter o estado Save-Data e vai estar disponível em qualquer lugar para uso na página. Com esse mecanismo ilustrado, vamos ver alguns exemplos de como podemos usá-lo para limitar a quantidade de dados que enviamos ao usuário.

Exibir imagens de baixa resolução em telas de alta resolução

Um caso de uso comum para imagens na Web envolve a veiculação de imagens em conjuntos de duas: uma imagem para telas "padrão" (1x) e outra que é duas vezes maior (2x) para telas de alta resolução (por exemplo, Retina Display). Essa classe de telas de alta resolução não está necessariamente limitada a dispositivos sofisticados e está se tornando cada vez mais comum. Nos casos em que uma experiência de aplicativo mais leve é preferível, pode ser prudente enviar imagens de resolução mais baixa (1x) para essas telas, em vez de variantes maiores (2x). Para fazer isso quando o cabeçalho Save-Data estiver presente, basta modificar a marcação que enviamos ao cliente:

if ($saveData === true) {
  // Send a low-resolution version of the image for clients specifying `Save-Data`.
  ?><img src="butterfly-1x.jpg" alt="A butterfly perched on a flower."><?php
}
else {
  // Send the usual assets for everyone else.
  ?><img src="butterfly-1x.jpg" srcset="butterfly-2x.jpg 2x, butterfly-1x.jpg 1x" alt="A butterfly perched on a flower."><?php
}

Esse caso de uso é um exemplo perfeito de como é fácil acomodar alguém que está pedindo especificamente para você enviar menos dados. Se você não quiser modificar a marcação no back-end, também é possível alcançar o mesmo resultado usando um módulo de reescrita de URL, como o mod_rewrite do Apache. Há exemplos de como fazer isso com pouca configuração.

Você também pode estender esse conceito para as propriedades CSS background-image simplesmente adicionando uma classe ao elemento <html>:

<html class="<?php if ($saveData === true): ?>save-data<?php endif; ?>">

A partir daí, você pode segmentar a classe save-data no elemento <html> no seu CSS para mudar a forma como as imagens são exibidas. Você pode enviar imagens de plano de fundo de baixa resolução para telas de alta resolução, como mostrado no exemplo de HTML acima, ou omitir determinados recursos.

Omitir imagens não essenciais

Alguns conteúdos de imagem na Web simplesmente não são essenciais. Embora essas imagens possam ser boas para o conteúdo, elas podem não ser desejáveis para quem está tentando aproveitar ao máximo os planos de dados limitados. No que é talvez o caso de uso mais simples de Save-Data, podemos usar o código de detecção de PHP anterior e omitir a marcação de imagem não essencial:

<p>This paragraph is essential content. The image below may be humorous, but it's not critical to the content.</p>
<?php
if ($saveData === false) {
  // Only send this image if `Save-Data` hasn't been detected.
  ?><img src="meme.jpg" alt="One does not simply consume data."><?php
}

Essa técnica pode ter um efeito pronunciado, como mostrado na figura abaixo:

Uma comparação de imagens não críticas
sendo carregadas quando o Save-Data está ausente, em comparação com as mesmas imagens sendo omitidas
quando o Save-Data está presente.
Uma comparação de imagens não críticas sendo carregadas quando o Save-Data está ausente, em comparação com as mesmas imagens sendo omitidas quando o Save-Data está presente.

Claro que omitir imagens não é a única possibilidade. Também é possível agir em Save-Data para evitar o envio de outros recursos não críticos, como determinadas famílias tipográficas.

Omitir fontes da Web não essenciais

Embora as fontes da Web geralmente não representem uma parte tão grande do payload total de uma página quanto as imagens, elas ainda são bastante usadas. Eles também não consomem uma quantidade insignificante de dados. Além disso, a maneira como os navegadores buscam e renderizam fontes é mais complicada do que você imagina, com conceitos como FOIT, FOUT e heurísticas de navegador que tornam a renderização uma operação sutil.

Portanto, pode ser razoável deixar de fora as fontes da Web não essenciais para usuários que querem experiências mais simples. O Save-Data torna isso uma tarefa razoavelmente simples.

Por exemplo, digamos que você tenha incluído a fonte Fira Sans do Google Fonts no seu site. A Fira Sans é uma excelente fonte para o corpo do texto, mas talvez não seja tão crucial para os usuários que estão tentando economizar dados. Ao adicionar uma classe de save-data ao elemento <html> quando o cabeçalho Save-Data está presente, podemos escrever estilos que invocam a família tipográfica não essencial no início, mas que depois a desativam quando o cabeçalho Save-Data está presente:

/* Opt into web fonts by default. */
p,
li {
  font-family: 'Fira Sans', 'Arial', sans-serif;
}

/* Opt out of web fonts if the `save-Data` class is present. */
.save-data p,
.save-data li {
  font-family: 'Arial', sans-serif;
}

Com essa abordagem, é possível deixar o snippet <link> do Google Fonts no lugar, porque o navegador carrega os recursos CSS de forma especulativa (incluindo fontes da Web) aplicando primeiro os estilos ao DOM e, em seguida, verificando se algum elemento HTML invoca algum dos recursos na folha de estilo. Se alguém acessar o site com o Save-Data ativado, a Fira Sans nunca será carregada porque o DOM estilizado nunca a invoca. A fonte Arial será usada. Não é tão boa quanto a Fira Sans, mas pode ser preferível para os usuários que tentam economizar nos planos de dados.

Resumo

O cabeçalho Save-Data não tem muita nuance. Ele está ativado ou desativado, e o aplicativo tem o ônus de fornecer experiências adequadas com base na configuração, independentemente do motivo.

Por exemplo, alguns usuários podem não permitir o modo de economia de dados se suspeitarem que haverá perda de conteúdo ou função do app, mesmo em uma situação de conectividade ruim. Por outro lado, alguns usuários podem ativar o recurso para manter as páginas o menor e mais simples possível, mesmo em uma boa situação de conectividade. É melhor que o app presuma que o usuário quer a experiência completa e ilimitada, até que você tenha uma indicação clara do contrário por uma ação explícita do usuário.

Como proprietários de sites e desenvolvedores web, vamos assumir a responsabilidade de gerenciar nosso conteúdo para melhorar a experiência do usuário para usuários com restrições de dados e custos.

Para mais detalhes sobre Save-Data e exemplos práticos excelentes, consulte Ajude seus usuários Save Data.