Oferecer aplicativos rápidos e leves com o Save-Data

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

A necessidade de páginas leves

Estatísticas do weblight

Todos concordam que páginas da Web mais rápidas e leves oferecem uma experiência do usuário mais satisfatória, permitem uma melhor compreensão e retenção do conteúdo e geram mais conversões e receita. Uma pesquisa do Google mostrou que "... páginas otimizadas carregam quatro vezes mais rápido do que a página original e usam 80% menos bytes. Como essas páginas carregam muito mais rapidamente, também percebemos um aumento de 50% no tráfego delas."

Além disso, embora o número de conexões 2G esteja finalmente em queda, o 2G ainda era a tecnologia de rede dominante em 2015. A penetração e a disponibilidade de 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 da página.

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 populares, eles têm desvantagens significativas, como compressã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 de pesquisa e 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 esse objetivo é 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 de 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 a usuários com restrições de custo e desempenho.

Os navegadores com suporte (abaixo) permitem que o usuário ative um *modo de economia de dados que dá permissão ao navegador para aplicar um conjunto de otimizações para reduzir a quantidade de dados necessários para renderizar a página. Quando esse recurso é exposto ou divulgado, o navegador pode solicitar imagens de resolução mais baixa, adiar o carregamento de alguns recursos ou encaminhar solicitações por meio de 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 e versões mais recentes 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.
  • A Opera 35 e versões mais recentes anunciam Save-Data quando o usuário ativa o modo Opera Turbo" no computador ou a opção Economia de dados" nos navegadores Android.
  • O Yandex 16.2+ anuncia Save-Data quando o modo turbo está ativado no computador ou em navegadores para dispositivos móveis.

Como detectar a configuração Save-Data

Para determinar quando entregar a experiência "light" aos usuários, o aplicativo pode verificar o cabeçalho de solicitação de sugestão de cliente Save-Data. Esse cabeçalho de solicitação indica a preferência do cliente por reduzir o uso de dados devido a custos de transferência altos, 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 de solicitação Save-Data a todas as solicitações de saída (HTTP e HTTPS). No 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 o Save-Data está ativado no JavaScript:

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

A verificação da presença do objeto connection no objeto navigator é essencial, já que representa a API Network Information, que é implementada apenas nos navegadores de Internet Chrome, Chrome para Android e Samsung. A partir daí, você só precisa verificar se navigator.connection.saveData é igual a true e pode implementar qualquer operação de salvamento de dados nessa condição.

O cabeçalho
Save-Data revelado nas Ferramentas para Desenvolvedores do Chrome, mostrado com a
extensão do Economizador de dados.
Como 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 de solicitação Save-Data e retornar uma resposta alternativa, como markup diferente, imagens e vídeos menores e assim por diante.

Dicas de implementação e práticas recomendadas

  1. Ao usar Save-Data, forneça alguns dispositivos de IU 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-os a usá-lo.
    • Permita que os usuários identifiquem e escolham o modo com as solicitações apropriadas e botões ou caixas de seleção intuitivos de ativar/desativar.
    • Quando o modo de economia de dados estiver selecionado, anuncie e ofereça uma maneira fácil e óbvia de desativar e reverter para a experiência completa, se desejar.
  2. Lembre-se de que aplicativos leves não são aplicativos menores. Eles não omitiram 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 visualizações de resolução mais baixa ou usar um mecanismo de carrossel com menos código.
    • Um app de pesquisa pode retornar menos resultados por vez, limitar o número de resultados de mídia pesada ou reduzir o número de dependências necessárias para renderizar a página.
    • Um site de notícias pode mostrar menos histórias, omitir categorias menos populares ou fornecer prévias de mídia menores.
  3. Forneça uma lógica do servidor para verificar o cabeçalho de solicitação Save-Data e considere fornecer uma resposta de página alternativa e mais leve quando ele estiver ativado. Por exemplo, reduzindo o número de recursos e dependências necessários, aplicando uma compactação de recursos mais agressiva etc.
    • Se você estiver enviando uma resposta alternativa com base no cabeçalho Save-Data, adicione-a à lista "Vary" (Vary: Save-Data) para informar aos caches upstream que eles precisam armazenar em cache e enviar essa versão somente se o cabeçalho de solicitação Save-Data estiver presente. Para mais detalhes, consulte as práticas recomendadas para interação com caches.
  4. Se você usar um worker de serviço, o aplicativo poderá detectar quando a opção de salvamento de dados estiver ativada verificando a presença do cabeçalho de solicitação Save-Data ou o valor da propriedade navigator.connection.saveData. Se estiver ativado, 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 e a tecnologia de conexão do usuário (consulte a API NetInfo). Por exemplo, talvez você queira oferecer a experiência leve a 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 tem interesse em economizar dados, por exemplo, quando está em roaming. Além disso, você pode aumentar a presença de Save-Data com a dica de cliente 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 navigator.deviceMemory.

Receitas

O que você pode alcançar com Save-Data é limitado apenas ao que você pode criar. Para você ter uma ideia do que é possível, vamos analisar alguns casos de uso. Você pode ter outros casos de uso enquanto lê este artigo. Então, sinta-se à vontade para experimentar e descobrir o que é possível.

Verificando Save-Data no código do lado do servidor

Embora o estado Save-Data seja algo que você pode detectar no JavaScript usando a propriedade navigator.connection.saveData, às vezes é preferível detectá-lo no lado do servidor. Em alguns casos, pode ocorrer falha na execução do JavaScript. Além disso, a detecção no lado do servidor é a única maneira de modificar a marcação antes de ela 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 servidor depende do idioma usado, mas a ideia básica é a mesma para qualquer back-end de aplicativo. No PHP, por exemplo, os cabeçalhos de solicitação são armazenados na matriz superglobal $_SERVER em índices que começam com HTTP_. Isso significa que você pode detectar o cabeçalho Save-Data verificando a existência e o valor da variável $_SERVER["HTTP_SAVE_DATA"] como esta:

// 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ê fizer essa verificação antes que qualquer marcação seja enviada ao cliente, a variável $saveData vai conter o estado Save-Data e estará disponível em qualquer lugar para uso na página. Com esse mecanismo ilustrado, vamos conferir alguns exemplos de como ele pode ser usado para limitar a quantidade de dados enviados ao usuário.

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

Um caso de uso comum para imagens na Web envolve veicular imagens em conjuntos de duas: uma imagem para telas "padrão" (1x) e outra imagem duas vezes maior (2x) para telas de alta resolução (por exemplo, Tela Retina). Essa classe de telas de alta resolução não é limitada a dispositivos de ponta 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 está presente, basta modificar a marcação enviada 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 quanto pouco esforço é necessário para acomodar alguém que está especificamente pedindo para você enviar menos dados. Se você não gosta de modificar a marcação no back-end, também pode conseguir o mesmo resultado usando um módulo de regravação de URL, como o mod_rewrite da Apache. Há exemplos de como fazer isso com relativamente pouca configuração.

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

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

Aqui, você pode segmentar a classe save-data no elemento <html> no CSS para mudar a forma como as imagens são enviadas. Você pode enviar imagens de plano de fundo de baixa resolução para telas de alta resolução, conforme mostrado no exemplo de HTML acima, ou omitir alguns 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 adições ao conteúdo, elas podem não ser desejáveis para quem tenta aproveitar ao máximo os planos de dados medidos. No que talvez seja 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 você pode ver na figura abaixo:

Uma comparação entre imagens não críticas que estão sendo carregadas quando Save-Data está ausente, com a mesma imagem sendo omitida quando 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 a mesma imagem sendo omitida quando o Save-Data está presente.

Omitir imagens não é a única possibilidade. Também é possível usar Save-Data para evitar o envio de outros recursos não críticos, como determinadas fontes.

Omitir fontes da Web não essenciais

Embora as fontes da Web geralmente não representem quase a mesma quantidade de payload de uma determinada página quanto as imagens costumam fazer, elas ainda são muito 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ê pode pensar, com conceitos como FOIT, FOUT e heurísticas de navegador que tornam a renderização uma operação sutil.

Portanto, é recomendável deixar de fora as fontes da Web não essenciais para usuários que querem experiências mais simples. O Save-Data facilita essa tarefa.

Por exemplo, digamos que você tenha incluído Fira Sans das Google Fonts no seu site. A Fira Sans é uma excelente fonte de texto principal, mas talvez não seja tão importante para os usuários que tentam salvar 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 de tipos não essenciais no início, mas depois 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;
}

Usando essa abordagem, você pode deixar o snippet <link> do Google Fonts no lugar, porque o navegador carrega recursos CSS (incluindo fontes da Web) de forma especulativa, primeiro aplicando estilos ao DOM e depois verificando se algum elemento HTML invoca algum dos recursos na folha de estilos. Se alguém passar com Save-Data ativado, o Fira Sans nunca será carregado porque o DOM com estilo nunca o invoca. Em vez disso, o Arial será usado. Ela não é tão boa quanto a Fira Sans, mas pode ser preferível para os usuários que tentam esticar os planos de dados.

Resumo

O cabeçalho Save-Data não tem muitas nuances. Ele está ativado ou desativado, e o aplicativo tem a responsabilidade de oferecer experiências adequadas com base na configuração, independentemente do motivo.

Por exemplo, alguns usuários podem não permitir o modo de salvamento de dados se suspeitarem que haverá uma 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 essa opção para manter as páginas o mais pequenas e simples possível, mesmo em uma situação de boa conectividade. É melhor que seu app presuma que o usuário quer a experiência completa e ilimitada até que você tenha uma indicação clara de que não é o caso por meio de uma ação explícita do usuário.

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

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