Vale a pena alterar toda a estrutura do arquivo de imagens do usuário para tirar proveito do cache simples do navegador?


9

Em um dos meus sites para dispositivos móveis, simplesmente armazeno as imagens de perfil dos meus usuários como '1.jpg' na pasta dos usuários e passo a partir daí para obter fotos extras que eles carregam. Isso significa que sempre que eles alteram a foto do perfil, por exemplo, o nome do arquivo permanece o mesmo.

Eu queria aproveitar o cache de imagens para que a mesma foto antiga não seja baixada repetidamente sempre que o perfil de um usuário for visualizado e revisto, mas, ao mesmo tempo, quero que os navegadores de meus usuários faça o download do novo caso ele tenha mudado.

Pelo que tenho lido, parece que a única maneira de realmente fazer isso é realmente usar nomes de arquivos aleatórios e acompanhar todos os nomes de arquivos no banco de dados, para que você possa definir um cache não expirado, enquanto recentemente as fotos alteradas são puxadas novamente, pois têm um novo nome de arquivo. A beleza da maneira como eu os estruturei até agora, no entanto, é que posso pular o banco de dados completamente e acessar os arquivos diretamente, pois sua localização é previsível.

Portanto, minha pergunta é: vale a pena alterar toda a estrutura de arquivos do meu site, além de adicionar o elemento DB, para o benefício do cache eterno e do download automático após o novo upload?

É um empreendimento enorme, mas se for considerado digno, não tenho problemas em avançar com essa mudança drástica. Eu só quero ter certeza de que é assim que os "garotos grandes" fazem isso, para que nunca mais precise alterar a estrutura do arquivo.

Obrigado.

Respostas:


7

Uma solução comumente usada é fazer com que os URLs de imagem se pareçam com isto:

http://www.example.com/path/to/images/1.jpg?v=123456

Aqui /path/to/images/1.jpgestá o caminho real da URL da imagem, enquanto ?v=123456apenas uma consulta fictícia está fixada no final da URL. A string de consulta pode ser qualquer coisa - um número de versão, um carimbo de data / hora, um hash do conteúdo da imagem - desde que você a altere sempre que a imagem é alterada e a mantém sempre que não é.

O truque é que o servidor da Web, quando solicitado a fornecer tal URL, ignorará a sequência de consultas, já que o URL de fato aponta para um arquivo estático. Porém, para o navegador do usuário (e para quaisquer proxies intermediários), URLs com cadeias de consulta diferentes serão completamente diferentes e, portanto, qualquer alteração na cadeia de consulta força o navegador a recarregar o arquivo.

Assim, você pode configurar seu servidor da Web para enviar Expirese Cache-Controlcabeçalhos HTTP para permitir armazenamento em cache indefinido, seguro de que você pode forçar um recarregamento alterando a cadeia de caracteres da consulta. Uma maneira de fazer isso, se você estiver usando o Apache com mod_expires , é colocar um .htaccessarquivo no diretório de imagens com as linhas:

ExpiresActive On
ExpiresDefault "access plus 1 year"

Essa técnica é usada por muitos sites populares. Por exemplo, se você olhar para a fonte HTML desta página, verá que a folha de estilos é carregada a partir de um URL como este:

http://cdn.sstatic.net/stackoverflow/all.css?v=7cd8ea9d6f1e

Aqui, a ?v=7cd8ea9d6f1eé uma string de consulta simulada, como eu descrevi acima; você pode confirmar isso alterando-o e vendo que, de fato, ele ainda retorna o mesmo arquivo.


Também é interessante, mas como eu acompanharia quando o arquivo foi modificado pela última vez e quando o navegador foi visualizado pela primeira vez, a fim de determinar quando devo dizer ao navegador do usuário para buscá-lo novamente (por exemplo, alterando o valor da consulta)?
ProgrammerGirl

11
Você não precisa acompanhar quando o arquivo foi visualizado. Basta acompanhar quando o arquivo foi alterado pela última vez (ou alguma outra propriedade apropriada) e incluí-lo na string de consulta. Dessa forma, sempre que o arquivo for alterado, o URL também será alterado.
Ilmari Karonen

Muito, muito, interessante. Então, presumivelmente, eu poderia buscar a propriedade "last modified" dos arquivos e apenas fazer com que o valor da consulta estivesse correto?
ProgrammerGirl

11
Sim, isso deve funcionar.
Ilmari Karonen

11
Não tenho nenhuma desvantagem significativa que eu saiba. Você pode acabar com cópias duplicadas de suas imagens nos índices dos mecanismos de pesquisa, mas pelo menos os principais mecanismos de pesquisa, como o Google, são bastante inteligentes em lidar com essas coisas, já que é um truque comum. De qualquer forma, esse problema pode ser atenuado enviando cabeçalhos HTTP rel = "canonical" e mantendo seus tempos de expiração modestos (digamos, apenas um mês ou uma semana em vez de um ano inteiro).
Ilmari Karonen

6

Há mais de uma maneira de armazenar em cache.

GET condicional

Se você estiver armazenando essas imagens no sistema de arquivos e as servindo diretamente através do servidor da web, provavelmente já está usando o get condicional . O servidor da Web usará automaticamente os metadados do sistema de arquivos para definir um cabeçalho ETAG e responderá automaticamente com "304 não modificado" se o navegador incluir If-Modified-Sinceou If-Matchescabeçalhos em sua solicitação. (Todos os navegadores irão.)

Nesse caso, a imagem inteira não é exibida novamente, portanto, você tem economia de largura de banda. No entanto, uma solicitação GET ainda será emitida, portanto você ainda terá a sobrecarga e a latência de uma solicitação.

Você pode diminuir um pouco o número de solicitações à custa da atualização do cache, solicitando que o servidor da Web defina Cache-Controlcabeçalhos com um public,max-age=Nvalor para suas imagens. Isso indica que os caches podem manter o recurso por no máximo max-agesegundos antes que eles precisem verificar se está atualizado.

No entanto, o HTTP define apenas uma maneira de invalidar uma entrada de cache, o que pode não se encaixar na semântica do aplicativo: se você POST ou PUT em um URL que atualiza a foto do perfil, responda com um Location: [url of photo]cabeçalho e a entrada de cache desse URL será invalidada.

(Esse é o mecanismo que permite armazenar em cache uma página da Web com comentários e, em seguida, recarregar à força a página pelo navegador depois que o usuário postar um novo comentário. O navegador responderia a um POST /commentcom 303 See Othere um Location: /page/with/comment. Observe que isso não foi usado para trabalhar no Firefox devido a um bug antigo .)

A menos que você tenha muito tráfego, essa abordagem ao cache é boa.

Alterando URLs

Uma URL é uma representação de um recurso; portanto, outra maneira de gerenciar o cache não é alterar os parâmetros de cache do recurso, mas criar um novo recurso com uma diretiva "cache para sempre". Essa é a abordagem que os "garotos grandes" favorecem, porque permite que eles não gerem solicitações extras, economizando muita largura de banda. A desvantagem é que requer muito mais contabilidade adicional.

Existem duas técnicas gerais para isso.

Cadeias de consulta

Servidores da Web ignoram cadeias de consulta ao exibir um arquivo do sistema de arquivos. Os caches, no entanto, não são : /1.jpg?t=12345e /1.jpg?t=67890são dois recursos independentes e completamente diferentes, mesmo que o servidor pense que eles são iguais.

Portanto, uma coisa fácil que você pode fazer é anexar o registro de data e hora do sistema de arquivos como uma string de consulta sempre que você fizer uma referência a um recurso em seu html e definir um Expirescabeçalho longo . O navegador armazenará esse recurso em cache para sempre e não fará nenhum GET, desde que a sequência de consultas não seja alterada.

Uma desvantagem é que é difícil ou impossível instruir o servidor da web do novo URL para um item se você deseja invalidar à força um cache. Por exemplo, se um navegador tiver uma página HTML em cache com uma /1.jpg?v=1referência, mas limpar a entrada /1.jpg?v=1(talvez o espaço no arquivo ou na memória fique sem memória), ele fará uma nova solicitação para /1.jpg?v=1. Enquanto isso, a imagem foi alterada para /1.jpg?v=2, a resposta adequada é:

  1. Sirva a versão antiga do arquivo. Você faria isso se quisesse que todos os recursos fossem consistentes entre si, como estavam em um determinado momento. Isto é o que você deve fazer com arquivos CSS, por exemplo, pois um novo arquivo css com um arquivo html antigo pode não funcionar corretamente!
  2. Redirecione para a nova versão do arquivo usando 301 Moved Permanently. Você faria isso se quisesse que todos os recursos fossem os mais novos possíveis.

Isso é difícil de ser feito apenas com um servidor da Web, o que significa que você precisa chamar um aplicativo da Web mesmo para solicitações de imagem, o que pode ser mais complicado e com muitos recursos. Os servidores da Web são muito rápidos na veiculação de arquivos; portanto, a sobrecarga de um aplicativo da Web pode acabar engolindo seus ganhos de largura de banda e latência.

Nomes de arquivo

Em vez de adicionar uma string de consulta, você altera o nome do arquivo. Isso significa que é fácil manter várias versões de arquivos no sistema de arquivos, mas você provavelmente precisará armazenar os metadados dos arquivos e fazer outra contabilidade de banco de dados para acompanhar seus recursos e seus nomes.


0

Ao ler sobre o status http 304 Not Modified, você poderá responder a uma solicitação de download com 304 e, com isso, informar ao servidor para usar os dados em cache, a fim de reenviá-los para o navegador. e leia esta pergunta /programming/2978496/make-php-page-return-304-not-modified-if-it-hasnt-been-modified


Interessante, mas essa é uma solução de "band-aid" para um esquema de arquivo problemático ou o esquema do meu arquivo é bom e só precisa dessa capacidade de armazenamento em cache? Além disso, como eu saberia quando o arquivo foi modificado pela última vez e quando o navegador foi exibido pela primeira vez, para determinar quando devo informar o navegador do usuário para buscá-lo novamente?
ProgrammerGirl

eu não estou tão familiarizado com isso, acho que Francis Avila sabe muito mais sobre isso #
Puggan Se
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.