Can’t make the #ChromeDevSummit this year? Catch all the content (and more!) on the livestream, or join your peers for a CDS Extended event at a hosted location nearby. To learn more, check out the Chrome Dev Summit 2019 website.

Cache de HTTP

A recuperação de algo pela rede é lenta e dispendiosa. Respostas grandes exigem várias idas e voltas entre o cliente e o servidor, o que retarda sua disponibilidade e processamento pelo navegador, além de gerar custos de dados para o visitante. Como resultado, a capacidade de armazenar em cache e reusar recursos previamente recuperados é um aspecto crítico da otimização do desempenho.

A boa notícia é que todo navegador é fornecido com uma implementação de um cache de HTTP. Tudo que você tem que fazer é garantir que cada resposta de servidor forneça as diretivas de cabeçalho HTTP corretas para instruir o navegador sobre quando e por quanto tempo ele pode armazenar a resposta em cache.

Solicitação HTTP

Quando o servidor retorna uma resposta, também emite uma coleção de cabeçalhos HTTP, descrevendo o tipo de conteúdo, o comprimento, as diretivas de armazenamento em cache, o token de validação e outras informações. Por exemplo, na troca acima, o servidor retorna uma resposta de 1.024 bytes, instrui o cliente a armazená-la em cache por até 120 segundos e fornece um token de validação ("x234dff") que pode ser usado após a expiração da resposta para verificar se o recurso foi modificado.

Validar respostas armazenadas em cache com ETags

TL;DR

  • O servidor usa a ETag de cabeçalho HTTP para comunicar um token de validação.
  • O token de validação permite verificações eficientes de atualização de recursos: nenhum dado é transferido se o recurso não foi alterado.

Suponha que se passaram 120 segundos desde nossa recuperação inicial e o navegador iniciou uma nova solicitação para o mesmo recurso. Primeiro, o navegador verifica o cache local e encontra a resposta anterior. O navegador não pode usar a resposta anterior porque ela está expirada. Nesse ponto, o navegador pode despachar uma nova solicitação e recuperar uma nova resposta completa. No entanto, isso é ineficiente porque não há motivo para fazer o download da mesma informação que já está no cache.

Esse é o problema que os tokens de validação, conforme especificado no cabeçalho ETag, foram projetados para resolver. O servidor gera e retorna um token arbitrário, que é normalmente um hash ou outra impressão digital do conteúdo do arquivo. O cliente não precisa saber como a impressão digital é gerada, basta enviá-la ao servidor na próxima solicitação. Caso a impressão digital ainda seja a mesma, isso significa que o recurso não mudou e você pode pular o download.

Exemplo de Cache-Control de HTTP

No exemplo anterior, o cliente fornece automaticamente o token ETag no cabeçalho de solicitação HTTP "If-None-Match". O servidor verifica o token em relação ao recurso atual. Se não houver alteração no token, o servidor retornará uma resposta "304 Not Modified", que informa ao navegador que a resposta no cache não foi alterada e pode ser renovada por outros 120 segundos. Não é necessário fazer o download da resposta novamente, o que economiza tempo e largura de banda.

Como desenvolvedor Web, como você pode aproveitar a revalidação eficiente? O navegador faz todo o trabalho por nós. O navegador detecta automaticamente se um token de validação já foi especificado antes, anexa o token de validação a uma solicitação de saída e atualiza os carimbos de data e hora do cache conforme a necessidade de acordo com a resposta recebida do servidor. A única ação que resta fazer é garantir que o servidor esteja fornecendo os tokens ETag necessários. Verifique a documentação do seu servidor para consultar os sinalizadores de configuração necessários.

Cache-Control

TL;DR

  • Cada recurso pode definir usar sua política de armazenamento em cache por meio do cabeçalho Cache-Control do HTTP.
  • As diretivas do Cache-Control controlam quem pode armazenar a resposta em cache e em que condições e por quanto tempo isso ocorre.

De uma perspectiva de otimização de desempenho, a melhor solicitação é a que não precisa se comunicar com o servidor: uma cópia local da resposta permite eliminar toda a latência de rede e evitar os custos de dados na transferência de dados. Para isso, a especificação HTTP permite que o servidor retorne diversas diretivas Cache-Control que controlam como e por quanto tempo o navegador e outros caches intermediários podem armazenar a resposta individual em cache.

Exemplo de Cache-Control de HTTP

"no-cache" e "no-store"

"no-cache" indica que a resposta retornada não pode ser usada para satisfazer uma solicitação subsequente para o mesmo URL sem antes verificar com o servidor se a resposta foi alterada. Como resultado, se um token de validação (ETag) adequado estiver presente, no-cache gera uma ida e volta para validar a resposta armazenada em cache, mas poderá eliminar o download caso o recurso não tenha sido alterado.

Em contrapartida, "no-store" é muito mais simples. Ele se limita a desautorizar o navegador e todos os caches intermediários a armazenar qualquer versão da resposta retornada, por exemplo, respostas contendo dados pessoais ou bancários privados. Sempre que o usuário pedir esse recurso, uma solicitação será enviada ao servidor e uma resposta completa será transferida por download.

"public" x "private"

Se a resposta for marcada como "public", poderá ser armazenada em cache, mesmo se tiver uma autenticação HTTP associada a ela e mesmo se o código de status da resposta não for normalmente armazenável em cache. Na maior parte das vezes, "public" não é realmente necessário porque informações explícitas de armazenamento em cache (como "max-age") indicam que a resposta é armazenável em cache.

Por outro lado, respostas "private" podem ser armazenadas em cache pelo navegador. No entanto, essas respostas são tipicamente destinadas a um único usuário, e, portanto, não podem ser armazenadas em cache em nenhum cache intermediário. Por exemplo, o navegador de um usuário pode armazenar em cache uma página HTML com informações de usuário privadas, mas uma CDN não pode armazenar a página em cache.

"max-age"

Essa diretiva especifica o tempo máximo, em segundos, que a resposta recuperada pode ser reutilizada, a partir do momento da solicitação. Por exemplo, "max-age=60" indica que a resposta pode ser armazenada em cache e reutilizada nos próximos 60 segundos.

Definir a política ideal de Cache-Control

Árvore de decisão do cache

Siga a árvore de decisão acima para determinar a política ideal de armazenamento em cache para um determinado recurso ou conjunto de recursos que seu aplicativo usa. Idealmente, você deve tentar armazenar no cache do cliente o maior número de respostas possível pelo maior período possível, bem como fornecer tokens de validação para cada resposta, permitindo uma revalidação eficiente.

Diretivas de Cache-Control & Explicação
max-age=86400 A resposta pode ser armazenada em cache pelo navegador e por qualquer cache intermediário (ou seja, é "pública") por até 1 dia (60 segundos x 60 minutos x 24 horas)
private, max-age=600 A resposta pode ser armazenada em cache pelo navegador do cliente por até 10 minutos (60 segundos x 10 minutos).
no-store A resposta não pode ser armazenada em cache e deve ser recuperada totalmente em cada solicitação.

De acordo com o HTTP Archive, entre os 300.000 sites principais (pela classificação do Alexa), o navegador pode armazenar em cache cerca de metade das respostas transferidas, o que é uma enorme economia para visualizações de página e visitas repetidas. Obviamente, isso não significa que seu aplicativo específico pode armazenar 50% dos recursos em cache. Alguns sites podem armazenar em cache mais de 90% de seus recursos, enquanto outros podem ter uma grande quantidade de dados privados ou dependentes do tempo que nunca podem ser armazenados em cache.

Confira suas páginas para identificar quais recursos podem ser armazenados em cache e garantir que retornem os cabeçalhos Cache-Control e ETag adequados.

Invalidar e atualizar respostas armazenadas em cache

TL;DR

  • As respostas armazenadas em cache local são usadas até que o recurso "expire".
  • A incorporação de uma impressão digital de conteúdo de arquivo no URL permite forçar a atualização para uma nova versão da resposta no cliente.
  • Cada aplicativo precisa definir a própria hierarquia de cache para ter o desempenho ideal.

Todas as solicitações HTTP efetuadas pelo navegador são antes encaminhadas ao cache do navegador, para verificar se há uma resposta válida armazenada no cache que possa ser usada para atender à solicitação. Se houver, a resposta será lida do cache, o que elimina a latência de rede e os custos de dados gerados pela transferência.

No entanto, e se você quiser atualizar ou invalidar uma resposta em cache? Por exemplo, suponha que você determinou que seus visitantes armazenem uma folha de estilo CSS por até 24 horas (max-age=86400), mas seu designer acabou de confirmar uma atualização que você quer disponibilizar a todos os usuários. Como você notifica todos os visitantes que têm uma cópia "obsoleta" do seu CSS armazenada em cache para que atualizem seus caches? Não é possível, a menos que se altere o URL do recurso.

Depois que uma resposta é armazenada em cache pelo navegador, a versão do cache é usada até que deixe de ser atual, conforme determinado por max-age, ou expire, ou seja eliminada do cache por algum outro motivo— por exemplo, se o usuário limpar o cache do navegador. Como resultado, usuários diferentes podem acabar usando versões diferentes do arquivo quando a página é construída. Os usuários que recuperaram recentemente o recurso usam a nova versão e os que armazenaram uma cópia anterior (mas ainda válida) no cache usam uma versão mais antiga da resposta.

Como podemos ter a melhor das opções: cache do lado do cliente e atualizações rápidas? Você pode alterar o URL do recurso e forçar o usuário a fazer o download da nova resposta sempre que seu conteúdo for alterado. Tipicamente, isso é feito incorporando uma impressão digital do arquivo, ou um número de versão, no nome do arquivo. Por exemplo, style.x234dff.css.

Hierarquia do cache

Com a capacidade de definir políticas de armazenamento em cache por recurso, é possível definir "hierarquias de cache" que permitem controlar não apenas o tempo de armazenamento em cache, mas também a rapidez com que novas versões são vistas pelos visitantes. Para ilustrar isso, analise o exemplo acima:

  • O HTML é marcado com "no-cache", o que significa que o navegador sempre revalida o documento em cada solicitação e recupera a versão mais recente caso o conteúdo seja alterado. Além disso, dentro da marcação HTML, você incorporou impressões digitais nos URLs para recursos CSS e JavaScript. Se o conteúdo desses arquivos for alterado, o HTML da página também será alterado e uma nova cópia da resposta HTML será transferida.
  • Os navegadores e caches intermediários (por exemplo, CDN) permitem o armazenamento de CSS em cache com expiração definida para 1 ano. Observe que você pode usar "expirações distantes no futuro" de 1 ano com segurança porque incorporou as impressões digitais do arquivo no nome do arquivo. Se o CSS for atualizado, o URL também será alterado.
  • No caso do JavaScript, a expiração também é definida para um ano, mas ele é marcado como privado, possivelmente porque contém alguns dados de usuário privados que a CDN não deve armazenar em cache.
  • A imagem é armazenada em cache sem versão ou impressão digital única, e a expiração é definida como um dia.

A combinação de ETag, Cache-Control e URLs únicos permite fornecer o melhor das duas opções: tempos de expiração longos, controle sobre onde a resposta pode ser armazenada e atualizações sob demanda.

Lista de verificação de armazenamento em cache

Não existe uma única política de cache ideal. Dependendo dos padrões de tráfego, do tipo de dados disponibilizado e de requisitos de atualização dos dados específicos de aplicativos, é obrigatório definir as configurações adequadas para cada recurso, bem como a "hierarquia geral de armazenamento em cache".

Veja a seguir algumas dicas e técnicas a considerar durante a definição da estratégia de armazenamento em cache:

  • Use URLs consistentes: se você disponibilizar o mesmo conteúdo em URLs diferentes, esse conteúdo será recuperado e armazenado várias vezes. Dica: os URLs diferenciam minúsculas de maiúsculas.
  • Verifique se o servidor fornece um token de validação (ETag): os tokens de validação eliminam a necessidade de transferir os mesmos bytes quando um recurso não foi alterado no servidor.
  • Identifique os recursos que podem ser armazenados em cache por intermediários: os recursos com respostas idênticas para todos os usuários são ótimos candidatos para armazenamento em cache por uma CDN ou por outros intermediários.
  • Determine o ciclo de vida ideal do cache para cada recurso: recursos diferentes podem ter requisitos de atualização diferentes. Faça uma auditoria e determine o max-age adequado para cada um.
  • Determine a melhor hierarquia de cache para seu site: a combinação de URLs de recursos com impressões digitais de conteúdo e os ciclos de vida curtos ou sem cache para documentos HTML permitem controlar a rapidez com que o cliente recebe atualizações.
  • Minimize o desligamento de usuários: alguns recursos são atualizados com maior frequência que outros. Se parte de um recurso (por exemplo, função JavaScript ou um conjunto de estilos CSS) for atualizada frequentemente, considere fornecer esse código em um arquivo separado. Isso permitirá que o restante do conteúdo (por exemplo, código de biblioteca que não é alterado com frequência) seja recuperado do cache e minimizará o volume de downloads sempre que uma atualização for recuperada.

Feedback

Was this page helpful?
Yes
What was the best thing about this page?
It helped me complete my goal(s)
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.
It had the information I needed
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.
It had accurate information
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.
It was easy to read
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.
Something else
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.
No
What was the worst thing about this page?
It didn't help me complete my goal(s)
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.
It was missing information I needed
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.
It had inaccurate information
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.
It was hard to read
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.
Something else
Thank you for the feedback. If you have specific ideas on how to improve this page, please create an issue.