una recursos publica política navegador memoria htaccess estáticos eficaz control con caracteristicas caché cache aprovechar almacenamiento caching

caching - recursos - memoria cache caracteristicas



almacenamiento en caché de archivos del lado del cliente (11)

¿Por qué no simplemente agregar un número de "versión" de cadena de consulta y actualizar la versión cada vez?

foo.js -> foo.js? version = 5

Todavía hay un poco de trabajo durante la compilación para actualizar los números de versión, pero no es necesario cambiar los nombres de archivo.

Si entiendo correctamente, un broswer almacena imágenes en caché, archivos JS, etc. según el nombre del archivo. Por lo tanto, existe el peligro de que si se actualiza uno de estos archivos (en el servidor), el navegador utilizará la copia en caché.

Una solución para este problema es cambiar el nombre de todos los archivos (como parte de la compilación), de modo que el nombre del archivo incluya un hash MD5 de su contenido, por ejemplo

foo.js -> foo_AS577688BC87654.js me.png -> me_32126A88BC3456BB.png

Sin embargo, además de cambiar el nombre de los archivos, todas las referencias a estos archivos deben cambiarse. Por ejemplo, una etiqueta como <img src="me.png"/> debe cambiar a <img src="me_32126A88BC3456BB.png"/> .

Obviamente, esto puede ser bastante complicado, especialmente si se considera que las referencias a estos archivos pueden crearse dinámicamente dentro del código del lado del servidor.

Por supuesto, una solución es deshabilitar completamente el almacenamiento en caché en el navegador (y cualquier almacenamiento en caché entre el servidor y el navegador) utilizando encabezados HTTP. Sin embargo, no tener almacenamiento en caché creará su propio conjunto de problemas.

¿Hay una solución mejor?

Gracias don


Cambiar el nombre de sus recursos es el camino a seguir, aunque usamos un número de compilación y lo incrustamos en el nombre del archivo en lugar de un hash MD5

foo.js -> foo.123.js

ya que significa que todos sus recursos pueden ser renombrados de manera determinista y resueltos en tiempo de ejecución.

Luego usamos controles personalizados para generar enlaces a recursos en la carga de la página en función del número de compilación que se almacena en una configuración de la aplicación.


Creo que una combinación de soluciones funciona mejor:

  1. Establecer las fechas de caducidad de la memoria caché para cada tipo de recurso (imagen, página, etc.) de forma adecuada para ese recurso, por ejemplo:

    • Es probable que sus páginas estáticas "Acerca de", "Contacto", etc. no vayan a cambiar más de unas pocas veces al año, por lo que podría poner fácilmente un tiempo de caché de un mes en estas páginas.
    • Las imágenes utilizadas en estas páginas pueden tener tiempos de caché eternos, ya que es más probable que sustituyas una imagen y luego que la cambies.
    • Las imágenes de avatar pueden tener un tiempo de expiración de un día.
  2. Algunos recursos necesitan fechas modificadas en sus nombres. Por ejemplo, avatares, imágenes generadas, y similares.

  3. Algunas cosas nunca deben ser cachés, nuevas páginas, contenido del usuario, etc. En estos casos, debe cachear en el servidor, pero nunca en el lado del cliente.

Al final, debe considerar detenidamente cada tipo de recurso para determinar qué tiempo de caché debe indicar al navegador que debe usar, y siempre ser conservador si no está seguro. Puede aumentar el tiempo más tarde, pero es mucho más dolor desenredar algo.


ETags aparentemente proporcionan una solución para esto ...

Según http://httpd.apache.org/docs/2.0/mod/core.html#fileetag , podemos configurar el navegador para que genere ETags en el tamaño del archivo (en lugar de time / inode / etc). Esta generación debe ser constante en múltiples implementaciones de servidores.

Solo habilítalo en (/etc/apache2/apache2.conf)

FileETag Size

y tu deberias ser bueno

De esa manera, puede simplemente hacer referencia a sus imágenes como <img src=''/path/to/foo.png'' /> y seguir usando toda la bondad del almacenamiento en caché de HTTP.


Es posible que desee revisar el enfoque adoptado por el plugin "uiperformance" de grails, que puede encontrar here . Hace muchas de las cosas que menciona, pero las automatiza (establece el tiempo de caducidad en mucho tiempo, y luego aumenta los números de versión cuando los archivos cambian).

Así que si estás usando grails, obtienes esto gratis. Si no lo eres, quizás puedas tomar prestadas las técnicas empleadas.

También, prestado de la página ui-performance, lea las siguientes 14 reglas .


Esto es realmente solo un problema si su servidor web establece un encabezado de "Caducidad" en el futuro (configurando algo como ExpiresDefault "access plus 10 years" en su configuración de Apache). De lo contrario, un navegador realizará un GET condicional, según la hora modificada y / o el Etag. Puede verificar lo que está sucediendo en su sitio utilizando un proxy web o una extensión como Firebug (en el panel de red). Su pregunta no menciona cómo está configurado su servidor web y qué encabezados está enviando con archivos estáticos.

Si no está configurando un encabezado Expires para un futuro lejano, no hay nada especial que deba hacer. Su servidor web generalmente manejará GET condicionales para archivos estáticos en función de la última vez que se modificó. Si está configurando un encabezado Expires para el futuro lejano, entonces sí, debe agregar algún tipo de versión al nombre del archivo como su pregunta y las otras respuestas ya han mencionado.


La mayoría de los navegadores modernos verifican el encabezado if-modified-since cuando un recurso almacenable en caché está en una solicitud HTTP. Sin embargo, no todos los navegadores admiten el encabezado if-modified-since.

Hay tres formas de "forzar" el navegador a cargar un recurso en caché.

Opción 1 Crear una cadena de consulta con una versión #. src="script.js?ver=21" . La desventaja es que muchos servidores proxy no almacenan en caché un recurso con cadenas de consulta. También requiere una actualización de todo el sitio para los cambios.

Opción 2 Cree un sistema de nombres para sus archivos src="script083010.js" . Sin embargo, la desventaja de la opción 1 es que esto también requiere actualizaciones en todo el sitio cada vez que se modifica un archivo.

Opción 3 Tal vez la solución más elegante, simplemente configure los encabezados de almacenamiento en caché: modificados por última vez y caducan en su servidor. El principal inconveniente de esto es que los usuarios pueden tener que volver a almacenar los recursos porque caducaron pero nunca cambiaron. Además, el encabezado modificado por última vez no funciona bien cuando el contenido se sirve desde varios servidores.

Aquí algunos recursos para revisar: Yahoo code.google.com/speed/page-speed/docs/caching.html AskApache.com


La mejor solución parece ser la versión de los nombres de archivo agregando la hora de la última modificación.

Puede hacerlo de esta manera: agregue una regla de reescritura a su configuración de Apache, así:

RewriteRule ^(.+)/.(.+)/.(js|css|jpg|png|gif)$ $1.$3

Esto redireccionará cualquier URL "versionada" a una "normal". La idea es mantener sus nombres de archivo iguales, pero beneficiarse de la caché. La solución para agregar un parámetro a la URL no será óptima con algunos proxies que no almacenan en caché las URL con los parámetros.

Entonces, en lugar de escribir:

<img src="image.png" />

Simplemente llame a una función de PHP:

<img src="<?php versionFile(''image.png''); ?>" />

Con versionFile () con este aspecto:

function versionFile($file){ $path = pathinfo($file); $ver = ''.''.filemtime($_SERVER[''DOCUMENT_ROOT''].$file).''.''; echo $path[''dirname''].''/''.str_replace(''.'', $ver, $path[''basename'']); }

¡Y eso es! El navegador solicitará image.123456789.png, Apache redirigirá esto a image.png, por lo que se beneficiará de la caché en todos los casos y no tendrá ningún problema desactualizado, sin tener que molestarse con el control de versiones de los nombres de archivo. .

Puede ver una explicación detallada de esta técnica aquí: http://particletree.com/notebook/automatically-version-your-css-and-javascript-files/


Seguimos un patrón similar al PJP, usando Rails y Nginx.

Queríamos que las imágenes de avatar de los usuarios se almacenaran en el caché del navegador, pero en el cambio de un avatar necesitábamos que la memoria caché se invalidara lo antes posible.

Agregamos un método al modelo de avatar para agregar una marca de tiempo al nombre del archivo:

return "/images/#{sourcedir}/#{user.login}-#{self.updated_at.to_s(:flat_string)}.png"

En todos los lugares del código donde se usaron los avatares, hicimos referencia a este método en lugar de a una URL. En la configuración de Nginx, agregamos esta reescritura:

rewrite "^/images/avatars/(.+)-[/d]{12}.png" /images/avatars/$1.png; rewrite "^/images/small-avatars/(.+)-[/d]{12}.png" /images/small-avatars/$1.png;

Esto significaba que si un archivo cambiaba, su URL en el HTML cambiaba, por lo que el navegador del usuario realizó una nueva solicitud para el archivo. Cuando la solicitud llegó a Nginx, se reescribió al nombre simple del archivo.


Sugeriría utilizar el almacenamiento en caché por ETags en esta situación, consulte en.wikipedia.org/wiki/HTTP_ETag . A continuación, puede utilizar el hash como el etag. Se seguirá enviando una solicitud para cada recurso, pero el navegador solo descargará los elementos que hayan cambiado desde la última descarga.

Lea en su servidor web / plataforma documentos sobre cómo usar etags correctamente, la mayoría de las plataformas decentes tienen soporte incorporado.


También he estado pensando en esto para un sitio que apoyo donde sería un gran trabajo cambiar todas las referencias. Tengo dos ideas:

1. Establezca los encabezados de caducidad de la memoria caché distante y aplique los cambios que sugiere para los archivos descargados con mayor frecuencia. Para otros archivos, configure los encabezados para que caduquen después de un tiempo muy corto, por ejemplo. 10 minutos. Luego, si tiene un tiempo de inactividad de 10 minutos al actualizar la aplicación, los cachés se actualizarán cuando los usuarios accedan al sitio. La navegación general del sitio debe mejorarse ya que los archivos solo necesitarán descargarse cada 10 minutos, no con cada clic.

2. Cada vez que se implementa una nueva versión de la aplicación en un contexto diferente que contiene el número de versión. p.ej. www.site.com/app_2_6_0/ No estoy muy seguro de esto ya que los marcadores de los usuarios se romperían en cada actualización.