Como manter tudo atualizado com o método desatualizado-while-revalidate

Uma ferramenta adicional para ajudar você a equilibrar a urgência e a atualização ao exibir seu aplicativo da web.

O que foi enviado?

O stale-while-revalidate ajuda os desenvolvedores a equilibrar a imediatismo (carregamento imediato do conteúdo armazenado em cache) e a atualização — garantindo que as atualizações do conteúdo armazenado em cache sejam usadas no futuro. Se você mantém um serviço ou biblioteca da Web de terceiros com atualizações regulares ou se seus recursos próprios tendem a ter ciclos de vida curtos, stale-while-revalidate pode ser uma adição útil às políticas de armazenamento em cache atuais.

O suporte para a configuração de stale-while-revalidate ao lado de max-age no cabeçalho de resposta Cache-Control está disponível no Chrome 75 e no Firefox 68.

Os navegadores que não oferecem suporte a stale-while-revalidate vão ignorar esse valor de configuração e usar max-age, como explicarei em breve...

O que isso significa?

Vamos dividir o stale-while-revalidate em duas partes: a ideia de que uma resposta armazenada em cache pode estar desatualizada e o processo de revalidação.

Primeiro, como o navegador sabe se uma resposta em cache está "desatualizada"? Um cabeçalho de resposta Cache-Control que contém stale-while-revalidate também precisa conter max-age, e o número de segundos especificado por max-age é o que determina a desatualização. Qualquer resposta armazenada em cache mais recente que max-age é considerada atual, e as mais antigas ficam desatualizadas.

Se a resposta armazenada localmente em cache ainda for recente, ela poderá ser usada no estado em que se encontra para atender à solicitação de um navegador. Da perspectiva de stale-while-revalidate, não há nada a fazer nesse cenário.

No entanto, se a resposta armazenada em cache estiver desatualizada, outra verificação com base na idade será realizada: a idade da resposta em cache está dentro da janela de tempo adicional fornecida pela configuração stale-while-revalidate?

Se a idade de uma resposta desatualizada cair nessa janela, ela será usada para atender à solicitação do navegador. Ao mesmo tempo, uma solicitação de "revalidação" será feita na rede de modo que não atrase o uso da resposta em cache. A resposta retornada pode conter as mesmas informações da resposta armazenada em cache ou ser diferente. De qualquer forma, a resposta de rede é armazenada localmente, substituindo o que estava armazenado em cache anteriormente e redefinindo o timer de atualização usado durante qualquer comparação futura de max-age.

No entanto, se a resposta desatualizada em cache for antiga o suficiente para ficar fora da janela stale-while-revalidate, ela não vai atender à solicitação do navegador. Em vez disso, o navegador recupera uma resposta da rede e a usa para atender à solicitação inicial e também preencher o cache local com uma nova resposta.

Exemplo em tempo real

Abaixo está um exemplo simples de uma API HTTP para retornar a hora atual, mais especificamente, o número atual de minutos após a hora.

Neste cenário, o servidor da Web usa este cabeçalho Cache-Control na resposta HTTP:

Cache-Control: max-age=1, stale-while-revalidate=59

Essa configuração significa que, se uma solicitação para o horário for repetida no próximo 1 segundo, o valor armazenado em cache anteriormente ainda vai ser atualizado e usado no estado em que se encontra, sem qualquer revalidação.

Se uma solicitação for repetida entre 1 e 60 segundos depois, o valor armazenado em cache ficará obsoleto, mas será usado para atender à solicitação da API. Ao mesmo tempo, "em segundo plano", uma solicitação de revalidação é feita para preencher o cache com um novo valor para uso futuro.

Se uma solicitação for repetida após mais de 60 segundos, a resposta desatualizada não será usada. Para atender à solicitação do navegador e à revalidação do cache, será necessário receber uma resposta da rede.

Confira uma análise desses três estados distintos, bem como a janela de tempo em que cada um deles se aplica ao nosso exemplo:

Um diagrama que ilustra as informações da seção anterior.

Quais são os casos de uso comuns?

Embora o exemplo acima para um serviço de API "minutos após a hora" seja artificial, ele ilustra o caso de uso esperado, ou seja, serviços que fornecem informações que precisam ser atualizadas, mas em que algum grau de inatividade é aceitável.

Exemplos menos inventados podem ser uma API para as condições climáticas atuais ou as principais manchetes que foram escritas na última hora.

Geralmente, qualquer resposta que é atualizada em um intervalo conhecido provavelmente será solicitada várias vezes e estiver estática dentro desse intervalo é uma boa candidata para armazenamento em cache de curto prazo por meio de max-age. Usar stale-while-revalidate, além de max-age, aumenta a probabilidade de que solicitações futuras possam ser atendidas a partir do cache com conteúdo mais recente, sem bloquear uma resposta de rede.

Como ele interage com os service workers?

Se você já ouviu falar de stale-while-revalidate, é provável que esteja no contexto de receitas usadas em um service worker.

O uso do revalidar durante a atualização usando um cabeçalho Cache-Control compartilha algumas similares com o uso em um service worker, e muitas das mesmas considerações sobre compensações de atualização e ciclos de vida máximos se aplicam. No entanto, há algumas considerações que você precisa considerar ao decidir se implementará uma abordagem baseada em service worker ou apenas confiar na configuração do cabeçalho Cache-Control.

Use uma abordagem de service worker se...

  • Você já está usando um service worker no seu app da Web.
  • Você precisa de um controle refinado sobre o conteúdo dos caches e quer implementar algo como uma política de expiração usada menos recentemente. O módulo Validade do cache do Workbox pode ajudar com isso.
  • Você quer receber uma notificação quando uma resposta desatualizada é alterada em segundo plano durante a etapa de revalidação. O módulo Atualização do cache de transmissão do Workbox pode ajudar com isso.
  • Esse comportamento stale-while-revalidate é necessário em todos os navegadores mais recentes.

Use uma abordagem de controle de cache se...

  • É melhor não lidar com a sobrecarga de implantação e manutenção de um service worker para seu app da Web.
  • Não há problema em permitir que o gerenciamento automático de cache do navegador impeça que os caches locais fiquem grandes demais.
  • Você não tem problemas com uma abordagem que não tem suporte em todos os navegadores modernos (desde julho de 2019, e essa compatibilidade pode aumentar).

Se você estiver usando um service worker e também tiver stale-while-revalidate ativado para algumas respostas por meio de um cabeçalho Cache-Control, o service worker, em geral, terá a "primeira crack" ao responder a uma solicitação. Se o service worker decidir não responder ou se, no processo de geração de uma resposta, ele fizer uma solicitação de rede usando fetch(), o comportamento configurado pelo cabeçalho Cache-Control vai acabar entrando em vigor.

Saiba mais

Imagem principal por Samuel Zeller.