Percebi que alguns navegadores (em particular, Firefox e Opera) são muito zelosos ao usar cópias em cache de arquivos .css e .js , mesmo entre as sessões do navegador. Isso causa um problema quando você atualiza um desses arquivos, mas o navegador do usuário continua usando a cópia em cache.
A questão é: qual é a maneira mais elegante de forçar o navegador do usuário a recarregar o arquivo quando ele foi alterado?
Idealmente, a solução não forçaria o navegador a recarregar o arquivo em todas as visitas à página. Vou postar minha própria solução como resposta, mas estou curioso para saber se alguém tem uma solução melhor e deixarei seus votos decidirem.
Atualização:
Depois de permitir a discussão aqui por um tempo, achei a sugestão de John Millikin e da5id útil. Acontece que existe um termo para isso: versão automática .
Publiquei uma nova resposta abaixo, que é uma combinação da minha solução original e da sugestão de John.
Outra idéia sugerida pelo SCdF seria anexar uma string de consulta falsa ao arquivo. (Algum código Python para usar automaticamente o registro de data e hora como uma string de consulta falsa foi enviado por pi .). No entanto, há alguma discussão sobre se o navegador armazenará ou não um arquivo em cache com uma string de consulta. (Lembre-se de que queremos que o navegador armazene em cache o arquivo e use-o em futuras visitas. Queremos que apenas busque o arquivo novamente quando ele tiver sido alterado.)
Como não está claro o que acontece com uma string de consulta falsa, não estou aceitando essa resposta.
ExpiresActive On ExpiresDefault "modification"
.iframe.contentWindow.location.reload(true)
. Veja o método (4) de stackoverflow.com/a/22429796/999120 - trata-se de imagens, mas o mesmo se aplica.Respostas:
Atualização: reescrita para incorporar sugestões de John Millikin e da5id . Esta solução é escrita em PHP, mas deve ser facilmente adaptada a outras linguagens.
Atualização 2: Incorporando comentários de Nick Johnson de que o
.htaccess
regex original pode causar problemas com arquivos comojson-1.3.js
. A solução é reescrever apenas se houver exatamente 10 dígitos no final. (Como 10 dígitos abrange todos os carimbos de data e hora de 9/9/2001 a 20/11/2286.)Primeiro, usamos a seguinte regra de reescrita em .htaccess:
Agora, escrevemos a seguinte função PHP:
Agora, onde quer que você inclua seu CSS, altere-o a partir deste:
Para isso:
Dessa forma, você nunca precisará modificar a tag do link novamente, e o usuário sempre verá o CSS mais recente. O navegador poderá armazenar em cache o arquivo CSS, mas quando você fizer alterações no CSS, o navegador o verá como um novo URL, portanto, não usará a cópia em cache.
Isso também pode funcionar com imagens, ícones favoritos e JavaScript. Basicamente, qualquer coisa que não seja gerada dinamicamente.
fonte
file_exists
cheque é realmente necessário?filemtime
retornará false em caso de falha; por que não atribuir o valor do tempo de filem a uma variável e verificar se é falso antes de renomear o arquivo? Isso reduziria uma operação desnecessária de arquivo que realmente aumentaria.Técnica simples do lado do cliente
Em geral, o armazenamento em cache é bom. Portanto, existem algumas técnicas, dependendo se você está solucionando o problema por conta própria ao desenvolver um site ou se está tentando controlar o cache em um ambiente de produção.
Os visitantes gerais do seu site não terão a mesma experiência que você está tendo ao desenvolver o site. Como o visitante médio acessa o site com menos frequência (talvez apenas algumas vezes por mês, a menos que você seja um Google ou hi5 Networks), é menos provável que eles tenham seus arquivos em cache, e isso pode ser suficiente. Se você deseja forçar uma nova versão no navegador, sempre pode adicionar uma sequência de consultas à solicitação e aumentar o número da versão ao fazer grandes alterações:
Isso garantirá que todos obtenham o novo arquivo. Funciona porque o navegador verifica a URL do arquivo para determinar se ele possui uma cópia no cache. Se o servidor não estiver configurado para fazer qualquer coisa com a sequência de consultas, ele será ignorado, mas o nome parecerá um novo arquivo para o navegador.
Por outro lado, se você estiver desenvolvendo um site, não deseja alterar o número da versão sempre que salvar uma alteração na sua versão de desenvolvimento. Isso seria entediante.
Portanto, enquanto você estiver desenvolvendo seu site, um bom truque seria gerar automaticamente um parâmetro de string de consulta:
Adicionar uma sequência de consultas à solicitação é uma boa maneira de versão de um recurso, mas para um site simples, isso pode ser desnecessário. E lembre-se, o cache é uma coisa boa.
Também é importante notar que o navegador não é necessariamente mesquinho para manter os arquivos em cache. Os navegadores têm políticas para esse tipo de coisa e geralmente estão seguindo as regras estabelecidas na especificação HTTP. Quando um navegador faz uma solicitação a um servidor, parte da resposta é um cabeçalho EXPIRES. Uma data que informa ao navegador quanto tempo deve ser mantido em cache. Na próxima vez em que o navegador encontrar uma solicitação para o mesmo arquivo, ele verá que possui uma cópia no cache e procurará a data EXPIRES para decidir se deve ser usado.
Então, acredite ou não, na verdade, é o seu servidor que está tornando o cache do navegador tão persistente. Você pode ajustar as configurações do servidor e alterar os cabeçalhos EXPIRES, mas a pequena técnica que escrevi acima é provavelmente uma maneira muito mais simples de você fazer isso. Como o armazenamento em cache é bom, geralmente você deseja definir essa data no futuro (um "Cabeçalho de expiração do futuro distante") e usar a técnica descrita acima para forçar uma alteração.
Se você estiver interessado em obter mais informações sobre HTTP ou sobre como essas solicitações são feitas, um bom livro é "Sites de alto desempenho", de Steve Souders. É uma introdução muito boa ao assunto.
fonte
<link href='myCss.css?dev=14141'...>
O plug- in mod_pagespeed do Google para apache fará a versão automática para você. É realmente liso.
Ele analisa o HTML ao sair do servidor da web (funciona com PHP, rails, python, HTML estático - qualquer coisa) e reescreve links para arquivos de imagem CSS, JS, para que incluam um código de identificação. Ele serve os arquivos nos URLs modificados com um controle de cache muito longo. Quando os arquivos mudam, os URLs são alterados automaticamente para que o navegador os busque novamente. Basicamente, funciona, sem nenhuma alteração no seu código. Ele também reduzirá seu código na saída.
fonte
Em vez de alterar a versão manualmente, recomendo que você use um hash MD5 do arquivo CSS real.
Portanto, seu URL seria algo como
Você ainda pode usar a regra de reescrita para remover o hash, mas a vantagem é que agora você pode definir sua política de cache como "cache para sempre", pois se a URL for a mesma, isso significa que o arquivo permanece inalterado.
Em seguida, você pode escrever um script de shell simples que calcule o hash do arquivo e atualize sua tag (você provavelmente deseja movê-lo para um arquivo separado para inclusão).
Basta executar esse script toda vez que o CSS mudar e você for bom. O navegador apenas recarregará seus arquivos quando eles forem alterados. Se você fizer uma edição e depois desfazê-la, não há problema em descobrir em qual versão você precisa retornar para que seus visitantes não façam o download novamente.
fonte
Não sei por que vocês estão sofrendo tanto para implementar esta solução.
Tudo o que você precisa fazer se obter o carimbo de data / hora modificado do arquivo e anexá-lo como uma string de consulta ao arquivo
No PHP, eu faria isso como:
filemtime é uma função PHP que retorna o carimbo de data / hora modificado do arquivo.
fonte
mycss.css?1234567890
.<link rel="stylesheet" href="mycss.css?<?php echo filemtime('mycss.css') ?>"/>
, no caso de alguns dos argumentos sobre este tópico sobre o cache URL de com variáveis GET (no formato sugerido) estão corretas?ver=
quem sabe!Você pode simplesmente colocar
?foo=1234
no final de sua importação de css / js, alterando 1234 para o que quiser. Dê uma olhada na fonte SO html para um exemplo.A idéia de que é isso? de qualquer maneira, os parâmetros são descartados / ignorados na solicitação e você pode alterar esse número ao lançar uma nova versão.
Nota: Há algum argumento sobre exatamente como isso afeta o armazenamento em cache. Eu acredito que a essência geral disso é que as solicitações GET, com ou sem parâmetros, devem ser alteráveis, portanto a solução acima deve funcionar.
No entanto, cabe ao servidor da web decidir se deseja aderir à parte da especificação e ao navegador que o usuário usa, pois ele pode seguir em frente e solicitar uma versão nova de qualquer maneira.
fonte
Eu ouvi isso chamado "versionamento automático". O método mais comum é incluir o mtime do arquivo estático em algum lugar da URL e removê-lo usando manipuladores de reescrita ou confs de URL:
Veja também:
fonte
As cerca de 30 respostas existentes são ótimos conselhos para um site de cerca de 2008. No entanto, quando se trata de um aplicativo moderno de página única (SPA), talvez seja hora de repensar algumas suposições fundamentais ... especificamente a idéia de que é desejável que o servidor da Web sirva apenas a versão única e mais recente de um Arquivo.
Imagine que você é um usuário que possui a versão M de um SPA carregada no seu navegador:
/some.template
/some.template
- você deseja que ele retorne a versão M ou N do modelo?Se o formato
/some.template
mudou entre as versões M e N (ou o arquivo foi renomeado ou o que for), você provavelmente não deseja que a versão N do modelo seja enviada ao navegador que está executando a versão antiga M do analisador . †Os aplicativos da Web enfrentam esse problema quando duas condições são atendidas:
Depois que o aplicativo precisar exibir várias versões em paralelo, a solução do cache e do "recarregamento" se tornará trivial:
/v<release_tag_1>/…files…
,/v<release_tag_2>/…files…
<script>
e<link>
etiquetas, etc. para apontar para esse arquivo em um dos diretórios versionadosEssa última etapa parece complicada, pois pode exigir a chamada de um construtor de URL para cada URL no código do servidor ou do cliente. Ou você pode fazer um uso inteligente da
<base>
tag e alterar a versão atual em um só lugar.† Uma maneira de contornar isso é ser agressivo ao forçar o navegador a recarregar tudo quando uma nova versão for lançada. Porém, para permitir a conclusão de qualquer operação em andamento, ainda pode ser mais fácil oferecer suporte a pelo menos duas versões em paralelo: v-current e v-previous.
fonte
base
tag! Quanto ao suporte ao código antigo: isso nem sempre é uma possibilidade, nem sempre é uma boa ideia. Novas versões de código podem oferecer suporte à quebra de alterações em outras partes de um aplicativo ou podem envolver correções de emergência, patches de vulnerabilidade etc. Eu ainda não implementei essa estratégia, mas sempre achei que a arquitetura geral deveria permitir que as implantações etiquetassem uma versão antigaobsolete
e forçassem um recarregamento na próxima vez que uma chamada assíncrona for feita (ou apenas desautorize forçosamente todas as sessões via WebSockets )Não use foo.css? Version = 1! Os navegadores não devem armazenar em cache URLs com variáveis GET. De acordo com http://www.thinkvitamin.com/features/webapps/serving-javascript-fast , embora o IE e o Firefox ignorem isso, o Opera e o Safari não! Em vez disso, use foo.v1234.css e use regras de reescrita para remover o número da versão.
fonte
No Laravel (PHP), podemos fazê-lo da seguinte maneira clara e elegante (usando o timestamp de modificação de arquivo):
E semelhante para CSS
Exemplo de saída html (
filemtime
tempo de retorno como carimbo de data e hora do Unix )fonte
O RewriteRule precisa de uma pequena atualização para arquivos js ou css que contêm uma versão de notação de ponto no final. Por exemplo, json-1.3.js.
Adicionei uma classe de negação de ponto [^.] Ao regex, para .number. é ignorado.
fonte
^(.*)\.[\d]{10}\.(css|js)$ $1.$2
[^.]
aqui. Além disso, não há nenhum benefício em escrever\d
dentro de uma classe de personagem -\d+
fará a mesma coisa. Conforme publicado, seu padrão corresponderá a qualquer número de caracteres (avidamente), depois a um ponto literal, depois a um não-ponto, a um ou mais dígitos, a um ponto, acss
oujs
então ao final do nome do arquivo. Nenhuma correspondência para sua entrada de amostra: regex101.com/r/RPGC62/1Para o ASP.NET 4.5 e superior, você pode usar o agrupamento de scripts .
Existem outros benefícios no pacote, incluindo desempenho aprimorado em carregamentos de primeira página com minificação.
fonte
Aqui está uma solução JavaScript pura
O item acima procurará a última vez que o usuário visitou seu site. Se a última visita foi antes do lançamento do novo código, ele será usado
location.reload(true)
para forçar a atualização da página do servidor.Normalmente, eu tenho esse como o primeiro script dentro
<head>
dele, por isso é avaliado antes que qualquer outro conteúdo seja carregado. Se uma recarga precisar ocorrer, dificilmente será percebida pelo usuário.Estou usando o armazenamento local para armazenar o carimbo de data e hora da última visita no navegador, mas você pode adicionar cookies à mistura se desejar oferecer suporte a versões mais antigas do IE.
fonte
Postagem interessante. Depois de ler todas as respostas aqui combinadas com o fato de que nunca tive problemas com cadeias de consulta "falsas" (o que não sei por que todos relutam em usar isso), acho que a solução (que elimina a necessidade de regras de reescrita do apache como na resposta aceita) é calcular um HASH curto do conteúdo do arquivo CSS (em vez da data e hora do arquivo) como uma string de consulta falsa.
Isso resultaria no seguinte:
É claro que as soluções datetime também fazem o trabalho no caso de editar um arquivo CSS, mas acho que é sobre o conteúdo do arquivo css e não sobre o datetime do arquivo, então por que misturá-los?
fonte
Para o meu desenvolvimento, acho que o chrome tem uma ótima solução.
https://developer.chrome.com/devtools/docs/tips-and-tricks#hard-reload
Com as ferramentas do desenvolvedor abertas, basta clicar e clicar no botão Atualizar e soltar quando passar o mouse sobre "Esvaziar o cache e recarregar".
Este é meu melhor amigo e é uma maneira super leve de conseguir o que você quer!
fonte
Agradecemos a Kip por sua solução perfeita!
Eu o estendi para usá-lo como um Zend_view_Helper. Como meu cliente executou sua página em um host virtual, eu também a estendi para isso.
Espero que ajude outra pessoa também.
Saúde e obrigado.
fonte
Não encontrou a abordagem DOM do lado do cliente criando o elemento nó do script (ou css) dinamicamente:
fonte
o google chrome tem a opção Recarregar com disco rígido , bem como a opção Cache vazio e Recarregar disco rígido. Você pode clicar e segurar o botão recarregar (no modo de inspeção) para selecionar um.
fonte
ant menu
>More Tools
>Developer Tools
, akaright click
>Inspect Element
. Há também uma configuração escondida em algum lugar nas ferramentas de desenvolvimento (eu esqueço a localização) para recarregar com força a cada recarga.Você pode forçar um "cache em toda a sessão" se adicionar o ID da sessão como um parâmetro espúrio do arquivo js / css:
Se você deseja um armazenamento em cache em toda a versão, adicione um código para imprimir a data do arquivo ou similar. Se você estiver usando Java, poderá usar uma tag personalizada para gerar o link de uma maneira elegante.
fonte
Digamos que você tenha um arquivo disponível em:
você pode anexar um parâmetro de consulta com informações de versão no URI, por exemplo:
ou você pode anexar informações da versão, por exemplo:
IMHO, o segundo método é melhor para arquivos CSS, pois eles podem se referir a imagens usando URLs relativos, o que significa que, se você especificar
background-image
o seguinte:seu URL será efetivamente:
Isso significa que, se você atualizar o número da versão usada, o servidor tratará isso como um novo recurso e não usará uma versão em cache. Se você basear seu número de versão no Subversion / CVS / etc. revisão significa que as alterações nas imagens referenciadas nos arquivos CSS serão notadas. Isso não é garantido com o primeiro esquema, ou seja, o URL
images/happy.gif
relativo a/styles/screen.css?v=1235
é/styles/images/happy.gif
que não contém nenhuma informação de versão.Eu implementei uma solução de armazenamento em cache usando essa técnica com servlets Java e simplesmente lide com solicitações
/v/*
com um servlet que delega para o recurso subjacente (ou seja/styles/screen.css
). No modo de desenvolvimento que defina o cache cabeçalhos que informam ao cliente para sempre verificar o frescor do recurso com o servidor (isso normalmente resulta em um 304 se você delegar Tomcat deDefaultServlet
eo.css
,.js
etc. arquivo não foi alterado), enquanto no modo de implantação Defino cabeçalhos que dizem "cache para sempre".fonte
<?php header( 'Location: folder1/login.phtml' ); ?>
.Você pode simplesmente adicionar algum número aleatório com o URL CSS / JS como
fonte
Para o ASP.NET, suponho que a próxima solução com opções avançadas (modo de depuração / versão, versões):
Arquivos Js ou Css incluídos desta maneira:
Global.JsPostfix e Global.CssPostfix são calculados da seguinte maneira em Global.asax:
fonte
Eu recentemente resolvi isso usando Python. Aqui o código (deve ser fácil de adotar para outros idiomas):
Esse código basicamente anexa o carimbo de data / hora dos arquivos como um parâmetro de consulta ao URL. A chamada da seguinte função
vai resultar em
A vantagem, é claro, é que você nunca precisará alterar seu html novamente. Tocar no arquivo CSS acionará automaticamente uma invalidação de cache. Funciona muito bem e a sobrecarga não é perceptível.
fonte
Se você estiver usando git + PHP, poderá recarregar o script do cache sempre que houver uma alteração no repositório git, usando o seguinte código:
fonte
Se você é um desenvolvedor que deseja evitar o armazenamento em cache, a guia rede do Chrome desativou a opção de cache. Caso contrário, você poderá fazê-lo sem uma estrutura de renderização do servidor usando duas tags de script.
fonte
Esta pergunta é super antiga e aparece logo que alguém procura no Google esse problema. Esta não é uma resposta para a pergunta da maneira que o op quer, mas uma resposta para os desenvolvedores com esse problema durante o desenvolvimento e o teste. E não consigo postar uma nova pergunta sobre este tópico, pois ela será marcada como duplicada.
Como muitos outros, eu só queria remover o cache brevemente.
"keep caching consistent with the file"
.. é muito aborrecido ..De um modo geral, não me importo de carregar mais - mesmo carregar novamente arquivos que não foram alterados - na maioria dos projetos - é praticamente irrelevante. Durante o desenvolvimento de um aplicativo - estamos carregando principalmente do disco, por diante
localhost:port
-, esseincrease in network traffic
problema não é uma questão de quebra de negócio .A maioria dos projetos pequenos está apenas brincando - eles nunca acabam em produção. então para eles você não precisa de mais nada ..
Portanto, se você usa as Ferramentas de desenvolvimento do Chrome , pode seguir esta abordagem de desativar cache, como na imagem abaixo:
E se você tiver problemas de cache do firefox :
Faça isso apenas no desenvolvimento, você também precisará de um mecanismo para forçar o recarregamento da produção, pois os usuários usarão módulos antigos invalidados pelo cache se você atualizar o aplicativo com freqüência e não fornecer um mecanismo de sincronização de cache dedicado, como os descritos nas respostas acima.
Sim, essas informações já estão nas respostas anteriores, mas eu ainda precisava fazer uma pesquisa no google para encontrá-las.
Espero que esta resposta seja muito clara e agora você não precisa.
fonte
Parece que todas as respostas aqui sugerem algum tipo de versão no esquema de nomenclatura, que tem suas desvantagens.
Os navegadores devem estar cientes do que armazenar em cache e do que não armazenar em cache, lendo a resposta dos servidores da web, em particular os cabeçalhos http - por quanto tempo esse recurso é válido? este recurso foi atualizado desde a última vez que o recuperei? etcetera.
Se as coisas estiverem configuradas 'corretamente', apenas a atualização dos arquivos do seu aplicativo deve (em algum momento) atualizar os caches dos navegadores. Você pode, por exemplo, configurar seu servidor da Web para dizer ao navegador para nunca armazenar em cache arquivos (o que é uma má ideia).
Uma explicação mais detalhada de como isso funciona está aqui https://www.mnot.net/cache_docs/#WORK
fonte
Simplesmente adicione este código, onde você deseja recarregar com força (forçar o navegador a recarregar arquivos CSS / JS em cache) Faça isso dentro do .load para que não seja atualizado como um loop
fonte
Basta usar o código do lado do servidor para adicionar a data do arquivo ... dessa forma, ele será armazenado em cache e recarregado apenas quando o arquivo for alterado
No ASP.NET
Isso pode ser simplificado para:
Adicionando um método de extensão ao seu projeto para estender a Página:
fonte
Sugiro implementar o seguinte processo:
versão seus arquivos css / js sempre que você implantar, algo como: screen.1233.css (o número pode ser sua revisão SVN se você usar um sistema de controle de versão)
reduza-os para otimizar os tempos de carregamento
fonte