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

O cabeçalho de solicitação de dica do cliente Save-Data disponível nos navegadores Chrome, Opera e Yandex, permite que os desenvolvedores ofereçam aplicativos mais leves, mais rápidos aos 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 proporcionam uma experiência do usuário mais satisfatória, permitem melhor compreensão e retenção de conteúdo e geram mais conversões e receita. A pesquisa do Google mostrou que "...as 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 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 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 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 populares, eles têm desvantagens substanciais: compressão de imagem e texto simples (e às vezes inaceitável), incapacidade de processar páginas seguras (HTTPS), otimização apenas de páginas visitadas por um resultado de 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 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 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 de economia de dados* que dá ao navegador permissão 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 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 compressã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 "Economia de dados" no dispositivo móvel ou a extensão "Economia de dados" em navegadores para computador.
  • O Opera 35 e versões mais recentes 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 e versões mais recentes anuncia Save-Data quando o modo Turbo está ativado em navegadores para computador ou dispositivos móveis.

Como detectar a configuração Save-Data

Para determinar quando oferecer a experiência "leve" aos usuários, seu aplicativo pode verificar o cabeçalho de solicitação de dica do cliente Save-Data. Esse cabeçalho da solicitação indica a preferência do cliente por 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 app do navegador anexa o cabeçalho da solicitação Save-Data a todas as solicitações de saída (HTTP e HTTPS). No momento da redação deste artigo, 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.
  }
}

É fundamental verificar a presença do objeto connection no objeto navigator, porque ele representa a API Network Information, que só é implementada nos navegadores Chrome, Google Chrome para Android e Samsung Internet. A partir daí, basta verificar se navigator.connection.saveData é igual a true, e você pode implementar qualquer operação de economia 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.
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 de 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: marcação 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 interface que o ofereçam suporte e permitam que os usuários alternem facilmente entre as experiências. Por exemplo:
    • Notifique os usuários de que Save-Data é compatível e incentive-os a usá-lo.
    • Permita que os usuários identifiquem e escolham o modo com avisos adequados e botões ou caixas de seleção intuitivos de ativação/desativação.
    • Quando o modo de economia de dados for selecionado, anuncie e ofereça uma maneira fácil e óbvia de desativá-lo e reverter para a experiência completa, se desejado.
  2. Lembre-se de que aplicativos leves não são aplicativos menores. Eles não omitem funcionalidades ou dados importantes, apenas estão mais cientes dos custos envolvidos e da experiência do usuário. Por 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 aplicativo de pesquisa pode retornar menos resultados por vez, limitar o número de resultados com muitos arquivos de mídia ou reduzir o número de dependências necessárias para renderizar a página.
    • Um site orientado a notícias pode mostrar menos histórias, omitir categorias menos populares ou fornecer visualizações de mídia menores.
  3. Forneça lógica de servidor para verificar o cabeçalho da solicitação Save-Data e considere oferecer 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á-la à lista Vary — Vary: Save-Data — para informar aos caches upstream que eles só devem armazenar em cache e veicular essa versão 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ê usa um service worker, o 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 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 disponibilizar 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 esteja interessado em economizar dados, por exemplo, ao fazer roaming. Além disso, você pode aumentar a presença de Save-Data com a dica do 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 do cliente navigator.deviceMemory.

Receitas

O que você pode alcançar com Save-Data é limitado apenas ao que você pode criar. Para dar uma ideia do que é possível, vamos analisar alguns casos de uso. Você pode criar outros casos de uso próprios ao ler este artigo. Portanto, fique à vontade para experimentar e ver o que é possível.

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

Embora o estado Save-Data seja algo que pode ser detectado no JavaScript pela propriedade navigator.connection.saveData, a detecção no lado do servidor às vezes é preferível. O JavaScript pode falhar na execução em alguns casos. Além disso, a detecção do 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 de 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 deve ser a mesma para qualquer back-end de aplicativo. No PHP, por exemplo, os cabeçalhos de solicitação são armazenados na $_SERVER superglobal matriz em índices que começam com HTTP_. Isso significa que você pode detectar o Save-Data cabeçalho verificando a existência e o valor da $_SERVER["HTTP_SAVE_DATA"] variável desta forma:

// 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 estará disponível para uso em qualquer lugar da página. Com esse mecanismo ilustrado, vamos conferir alguns exemplos de como podemos usá-lo para limitar a quantidade de dados que enviamos ao usuário.

Veicular imagens de baixa resolução para 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 imagem duas vezes maior (2x) para telas de alta resolução (por exemplo, Retina Display). Essa classe de telas de alta resolução não se limita necessariamente a dispositivos sofisticados e está se tornando cada vez mais comum. Nos casos em que uma experiência de aplicativo mais leve é preferível, é 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 atender a alguém que está pedindo especificamente para enviar menos dados. Se você não quiser modificar a marcação no back-end, também poderá alcançar o mesmo resultado usando um módulo de reescrita de URL, como o Apache's mod_rewrite. Há exemplos de como fazer isso com uma configuração relativamente pequena.

Você também pode estender esse conceito às propriedades background-image do CSS 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 veiculadas. Você pode enviar imagens de fundo de baixa resolução para telas de alta resolução, conforme mostrado no exemplo de HTML acima, ou omitir determinados recursos.

Omitir imagens não essenciais

Alguns conteúdos de imagem na Web 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 você pode ver na figura abaixo:

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

É claro que omitir imagens não é a única possibilidade. Você também pode agir em Save-Data para deixar de enviar 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 total de uma página que as imagens, elas ainda são bastante populares. Elas 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 do navegador que tornam a renderização uma operação sutil.

Portanto, é razoável que você queira deixar de lado as fontes da Web não essenciais para usuários que querem experiências mais enxutas. Save-Data torna isso algo razoavelmente fácil de fazer.

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

Usando essa abordagem, você pode deixar o snippet <link> do Google Fonts em lugar, porque o navegador carrega especulativamente recursos CSS (incluindo fontes da Web) aplicando estilos ao DOM e, em seguida, verificando se algum elemento HTML invoca algum dos recursos na folha de estilo. Se alguém passar com Save-Data ativado, a Fira Sans nunca será carregada porque o DOM estilizado nunca a invoca. Em vez disso, a Arial será ativada. Não é tão boa quanto a Fira Sans, mas pode ser preferível para os usuários que tentam estender os 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 ativá-lo como um curso normal para manter as páginas o mais pequenas e simples possível, mesmo em uma boa situação de conectividade. É melhor que o app assuma que o usuário quer a experiência completa e ilimitada até que você tenha uma indicação clara do contrário 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 para usuários com restrições de dados e custos.

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