Como expirar a imagem e forçar o recarregamento no Apache somente quando o arquivo for alterado no servidor

1

Eu tenho um aplicativo PHP em execução em um servidor Apache2. Comecei com o Boilerplate HTML5 e o .htaccess inclui a política de expiração "1 mês" para todas as imagens. Por exemplo:

ExpiresByType image/jpeg                            "access plus 1 month"

Meu aplicativo também permite que um usuário substitua uma imagem existente por uma nova (sob o mesmo nome e caminho). No entanto, uma vez substituído, o usuário continua a ver a imagem antiga até que a página seja atualizada vigorosamente (digamos, Ctrl - F5 ).

Percebi nos logs que, tecnicamente, como a imagem está configurada para expirar daqui a 1 mês, o navegador não solicita o servidor. Apenas em uma atualização de força o navegador solicita, nesse ponto o Apache2 pode emitir um 304 (se o arquivo nunca mudou) ou enviar a nova imagem com um 200 (se ele mudou).

O que eu quero é um mecanismo simples e direto para:

  • Mantenha a configuração existente onde as imagens expiram daqui a 1 mês. Os navegadores não precisam buscá-lo se já o tiverem.
  • Mas, se a imagem for atualizada pelo usuário, o navegador terá automaticamente a nova imagem. Não deve haver necessidade de dizer ao usuário para forçar uma atualização.
  • A busca de nova imagem também deve se estender a outros usuários ou outro navegador após o último ponto.

Como alternativa, eu não me importaria se eu pudesse definir condicionalmente a política de expiração como "imediata" apenas para um determinado caminho (as imagens em outras pastas devem seguir a política de expiração geral). Eu posso viver com os numerosos 304 s. Eu acho.

Eu não quero simplesmente mudar o nome do arquivo para um novo. Os nomes dos arquivos são gerados dinamicamente, e existem vários - rastrear seus "novos nomes" aumentaria a complexidade. (Embora, se não houver outra solução fácil, terei que explorar isso.)

    
por ADTC 27.03.2016 / 07:30

1 resposta

1

Você está pedindo muito: configurando explicitamente que alguns dados são válidos por um mês, não é assim que você muda de ideia. Em geral, você terá que se decidir.

  • Se os 304s não te ferirem: Encurtar o intervalo pode ser uma solução
  • As atenuações populares desse problema envolvem um parâmetro de carimbo de data / hora na imagem: Não carregue logo.png , mas carregue logo.png?t=20160327083700 , em que o carimbo de data / hora é estático em todo o seu aplicativo (e atualizado a seu critério) ou o último data de alteração do arquivo (o que adicionará carga no servidor)
  • Após seu comentário, você também poderá adicionar o registro de data e hora em outro lugar no caminho (para que os nomes das imagens permaneçam os mesmos): /20160327083700/logo.png . No entanto, leia meu último parágrafo sobre otimização prematura

Desde que você diga a todos que um recurso é válido por um longo tempo, não se surpreenda se eles aceitarem sua palavra e reutilizá-lo até que o tempo acabe.

Para o parâmetro timestamp acima, usei um registro de data e hora algo legível (por exemplo, hoje). Você provavelmente quer usar apenas milissegundos não formatados desde 1970 ou qualquer valor não formatado que obtenha facilmente. Só precisa mudar a cada atualização do arquivo.

Editar: conforme você informa no comentário, os navegadores tendem a interpretar o ? no URL como ignorado pelo cache - e solicitar melhor o recurso novamente no início. Com isso, sua melhor aposta seria encurtar o intervalo de tempo. Especialmente quando você diz que sobreviverá aos 304s: desça para "access plus 1 hour" (ou até 10 minutos). Esta seria a coisa certa a fazer de qualquer maneira: o estado que conteúdo pode ser armazenado em cache por 1 mês se e somente se puder ser armazenado em cache por 1 mês.

E, a propósito, deixe-me lembrá-lo do velho ditado "otimização prematura é a raiz de todo o mal" - aposto que "access plus 1 month" não veio de nenhuma sessão de ajuste de desempenho, mas sim de sua suposição. E, como você vê com essa pergunta, essa otimização prematura realmente gera muito trabalho extra para resolver os conflitos que ela introduziu.

    
por 27.03.2016 / 08:47