Estou tentando descobrir como lidar adequadamente com o cache do navegador da Web para aplicativos de página única.
Eu tenho um design bastante típico: vários arquivos HTML, JS e CSS implementando o SPA e um monte de dados JSON consumidos pelo SPA. Os problemas surgem quando desejo enviar uma atualização: atualizo a parte estática do site e o código que gera o JSON ao mesmo tempo, mas os navegadores clientes geralmente têm a parte estática em cache, portanto, o código antigo tenta processar os novos dados e pode (dependendo das alterações feitas) ter problemas. (Em particular, o IE parece mais agressivo do que o Chrome ou o Firefox sobre o uso de JS em cache sem revalidar.)
Qual é a melhor maneira de lidar com isso?
- Verifique se minhas alterações no JSON são compatíveis com versões anteriores e assuma que os caches do navegador expirarão em um prazo razoável.
- Incorpore algum tipo de número de versão no JS estático e no JSON e execute
window.location.reload(true);
se não corresponderem. - Descubra a combinação apropriada de cabeçalhos (
must-revalidate
ouno-cache
qualquer outra coisa; as fontes variam de como fazer isso) para garantir que os navegadores sempre revalidem todos os recursos em cada carregamento, mesmo que isso signifique algumas viagens extras para carregar o site. - Microgerencie meu controle de cache e expire os cabeçalhos para que o conteúdo estático expire quando eu desejar enviar uma atualização.
- Algo mais?
javascript
web-applications
caching
Josh Kelley
fonte
fonte
Respostas:
Você precisa de uma solução de bloqueio de cache . O papel do bloqueio de cache é:
Em um projeto baseado no Grunt, é comum usar o grunt-rev para garantir que todos os arquivos que precisam ser atualizados tenham nomes exclusivos, com base em seu conteúdo.
Se você garantir que seus arquivos JSON recebam nomes de arquivos com armazenamento em cache, juntamente com as referências a eles em seu Javascript, os clientes sempre carregarão os arquivos JSON que o Javascript espera.
A vantagem da nomeação de arquivo baseada em hash é que os arquivos que não foram alterados terão os mesmos nomes de arquivo após a interrupção do cache, para que os navegadores possam continuar a usar com segurança o conteúdo em cache quando ele não for alterado.
Obviamente, esse é o tipo de coisa que você deseja automatizar como parte da produção do seu projeto, para que você não precise acompanhar manualmente a alteração dos nomes e referências de arquivos.
fonte
Você pode usar
if-modified-since + last-modified
ouif-none-match + etag
cabeçalhos junto com ocache-control
cabeçalho apropriado . (Pode haver erros no navegador , mas nada que você não possa gerenciar nos navegadores recentes.)Se os arquivos forem estáticos, sugiro que você use
if-modified-since
, porque isso pode ser feito automaticamente com um servidor HTTP bem configurado. Ele deve enviar 304 se o arquivo não for modificado desde o último download.Eu não acho que o seu número 1 e o número 2 funcionariam a longo prazo. O nº 3 ou nº 4 pode funcionar. O nº 3 é mais simples, mas você precisa aprender a lidar com esse problema apenas uma vez. Então, eu tentaria o nº 4 se fosse você, mas a solução pode depender de quais navegadores seus clientes usam ... Por exemplo, o IE8 tem problemas ao atualizar o cache ajax, etc ...
fonte
Se você pode incluir o Java Servlet Filter no seu SPA, aqui está uma solução funcional: CorrectBrowserCacheHandlerFilter.java
Basicamente, quando o navegador solicita os arquivos estáticos, o servidor redireciona todas as solicitações para o mesmo, mas com um parâmetro de consulta de hash (
?v=azErT
por exemplo), que depende do conteúdo do arquivo estático de destino.Fazendo isso, o navegador nunca armazenará em cache os arquivos estáticos declarados no seu,
index.html
por exemplo (porque sempre receberá um302 Moved Temporarily
), mas armazenará apenas em cache os arquivos com a versão hash (o servidor responderá200
por eles). Portanto, o cache do navegador será usado com eficiência para esses arquivos estáticos com a versão hash.Disclaimer: Eu sou o autor de
CorrectBrowserCacheHandlerFilter.java
.fonte