una navegadores navegador los limpiar evitar como caché cache busting borrar archivos aplicación actualizar javascript css caching auto-versioning

javascript - navegadores - limpiar cache navegador jquery



¿Cómo forzar al navegador a recargar archivos CSS/JS en caché? (30)

¡No uses foo.css? Version = 1! Se supone que los navegadores no deben almacenar en caché las direcciones URL con variables GET. De acuerdo con http://www.thinkvitamin.com/features/webapps/serving-javascript-fast , aunque IE y Firefox ignoran esto, ¡Opera y Safari no! En su lugar, use foo.v1234.css, y use las reglas de reescritura para eliminar el número de versión.

Me he dado cuenta de que algunos navegadores (en particular, Firefox y Opera) son muy entusiastas en el uso de copias en caché de archivos .css y .js , incluso entre sesiones de navegador. Esto lleva a un problema cuando actualiza uno de estos archivos, pero el navegador del usuario sigue utilizando la copia en caché.

La pregunta es: ¿cuál es la forma más elegante de obligar al navegador del usuario a volver a cargar el archivo cuando ha cambiado?

Idealmente, la solución no obligaría al navegador a volver a cargar el archivo en cada visita a la página. Publicaré mi propia solución como respuesta, pero tengo curiosidad por saber si alguien tiene una solución mejor y dejaré que sus votos decidan.

Actualizar:

Después de permitir la discusión aquí por un tiempo, he encontrado que la sugerencia de John Millikin y da5id es útil. Resulta que hay un término para esto: auto-versioning .

He publicado una nueva respuesta a continuación, que es una combinación de mi solución original y la sugerencia de John.

Otra idea sugerida por SCdF sería agregar una cadena de consulta falsa al archivo. (Algunos códigos de Python para usar automáticamente la marca de tiempo como una cadena de consulta falsa fue enviada por pi ). Sin embargo, existe cierta discusión sobre si el navegador almacenará o no un archivo con una cadena de consulta. (Recuerde que queremos que el navegador almacene en caché el archivo y lo use en futuras visitas. Solo queremos que recupere el archivo cuando haya cambiado).

Como no está claro qué sucede con una cadena de consulta falsa, no estoy aceptando esa respuesta.


Aquí hay una solución de JavaScript puro.

(function(){ // Match this timestamp with the release of your code var lastVersioning = Date.UTC(2014, 11, 20, 2, 15, 10); var lastCacheDateTime = localStorage.getItem(''lastCacheDatetime''); if(lastCacheDateTime){ if(lastVersioning > lastCacheDateTime){ var reload = true; } } localStorage.setItem(''lastCacheDatetime'', Date.now()); if(reload){ location.reload(true); } })();

Lo anterior buscará la última vez que el usuario visitó su sitio. Si la última visita fue antes de lanzar el nuevo código, usa location.reload(true) para forzar la actualización de la página desde el servidor.

Por lo general, tengo este primer script dentro del <head> por lo que se evalúa antes de que se cargue cualquier otro contenido. Si es necesario que se produzca una recarga, es difícil que el usuario lo note.

Estoy usando el almacenamiento local para almacenar la marca de tiempo de la última visita en el navegador, pero puede agregar cookies a la mezcla si quiere admitir versiones anteriores de IE.


Digamos que tienes un archivo disponible en:

/styles/screen.css

puede agregar un parámetro de consulta con información de versión en el URI, por ejemplo:

/styles/screen.css?v=1234

o puede anteponer información de la versión, por ejemplo:

/v/1234/styles/screen.css

En mi humilde opinión, el segundo método es mejor para los archivos CSS porque pueden referirse a imágenes usando URL relativas, lo que significa que si especifica una background-image como la siguiente:

body { background-image: url(''images/happy.gif''); }

su URL será efectivamente:

/v/1234/styles/images/happy.gif

Esto significa que si actualiza el número de versión utilizado, el servidor lo tratará como un nuevo recurso y no utilizará una versión en caché. Si basa su número de versión en Subversion / CVS / etc. revisión esto significa que se notarán los cambios a las imágenes referenciadas en archivos CSS. Eso no está garantizado con el primer esquema, es decir, las images/happy.gif URL images/happy.gif relativas a /styles/screen.css?v=1235 es /styles/images/happy.gif que no contiene ninguna información de versión.

He implementado una solución de almacenamiento en caché utilizando esta técnica con servlets de Java y simplemente manejo las solicitudes a /v/* con un servlet que delega en el recurso subyacente (es decir, /styles/screen.css ). En el modo de desarrollo, establezco los encabezados de almacenamiento en caché que le dicen al cliente que siempre verifique la actualización del recurso con el servidor (esto generalmente resulta en un 304 si usted delega el DefaultServlet de Tomcat y el archivo .css , .js , etc. no ha cambiado) ) Mientras estaba en modo de implementación, puse encabezados que dicen "caché para siempre".


El complemento mod_pagespeed de Google para apache se encargará automáticamente de la versión. Es realmente resbaladizo.

Analiza HTML en su salida del servidor web (funciona con PHP, rieles, python, HTML estático, cualquier cosa) y vuelve a escribir enlaces a CSS, JS, archivos de imagen para que incluyan un código de identificación. Sirve los archivos en las URL modificadas con un control de caché muy largo. Cuando los archivos cambian, automáticamente cambia las URL para que el navegador tenga que recuperarlos. Básicamente simplemente funciona, sin ningún cambio en su código. Incluso se reducirá su código en la salida también.


En Laravel (PHP) podemos hacerlo de la siguiente manera clara y elegante (usando la marca de tiempo de modificación de archivos):

<script src="{{ asset(''/js/your.js?v=''.filemtime(''js/your.js'')) }}"></script>

Y similar para CSS

<link rel="stylesheet" href="{{asset(''css/your.css?v=''.filemtime(''css/your.css''))}}">


En lugar de cambiar la versión manualmente, recomendaría usar un hash MD5 del archivo CSS real.

Entonces tu URL sería algo así como

http://mysite.com/css/[md5_hash_here]/style.css

Aún puede usar la regla de reescritura para eliminar el hash, pero la ventaja es que ahora puede configurar su política de caché en "caché para siempre", ya que si la URL es la misma, eso significa que el archivo no se modifica.

Luego puede escribir un script de shell simple que calcule el hash del archivo y actualice su etiqueta (probablemente querrá moverlo a un archivo separado para su inclusión).

Simplemente ejecuta ese script cada vez que CSS cambie y estarás bien. El navegador SOLO recargará sus archivos cuando se modifiquen. Si hace una edición y luego la deshace, no hay problema en averiguar qué versión necesita volver para que sus visitantes no vuelvan a descargar.


Gracias a Kip por su solución perfecta!

Lo extendí para usarlo como Zend_view_Helper. Como mi cliente ejecutó su página en un servidor virtual, también lo extendí para eso.

Espero que ayude a alguien más también.

/** * Extend filepath with timestamp to force browser to * automatically refresh them if they are updated * * This is based on Kip''s version, but now * also works on virtual hosts * @link http://.com/questions/118884/what-is-an-elegant-way-to-force-browsers-to-reload-cached-css-js-files * * Usage: * - extend your .htaccess file with * # Route for My_View_Helper_AutoRefreshRewriter * # which extends files with there timestamp so if these * # are updated a automatic refresh should occur * # RewriteRule ^(.*)/.[^.][/d]+/.(css|js)$ $1.$2 [L] * - then use it in your view script like * $this->headLink()->appendStylesheet( $this->autoRefreshRewriter($this->cssPath . ''default.css'')); * */ class My_View_Helper_AutoRefreshRewriter extends Zend_View_Helper_Abstract { public function autoRefreshRewriter($filePath) { if (strpos($filePath, ''/'') !== 0) { // path has no leading ''/'' return $filePath; } elseif (file_exists($_SERVER[''DOCUMENT_ROOT''] . $filePath)) { // file exists under normal path // so build path based on this $mtime = filemtime($_SERVER[''DOCUMENT_ROOT''] . $filePath); return preg_replace(''{//.([^./]+)$}'', ".$mtime./$1", $filePath); } else { // fetch directory of index.php file (file from all others are included) // and get only the directory $indexFilePath = dirname(current(get_included_files())); // check if file exist relativ to index file if (file_exists($indexFilePath . $filePath)) { // get timestamp based on this relativ path $mtime = filemtime($indexFilePath . $filePath); // write generated timestamp to path // but use old path not the relativ one return preg_replace(''{//.([^./]+)$}'', ".$mtime./$1", $filePath); } else { return $filePath; } } } }

Saludos y gracias.



La RewriteRule necesita una pequeña actualización para los archivos js o css que contienen una versión de notación de puntos al final. Por ejemplo, json-1.3.js.

Agregué una clase de negación de puntos [^.] A la expresión regular, por lo que .number. se ignora

RewriteRule ^(.*)/.[^.][/d]+/.(css|js)$ $1.$2 [L]


Las más o menos 30 respuestas existentes son un gran consejo para un sitio web de circa 2008. Sin embargo, cuando se trata de una aplicación moderna de una sola página (SPA), podría ser el momento de repensar algunas suposiciones fundamentales ... específicamente la idea de que es deseable que el servidor web sirva solo la versión más reciente y única de un servidor web. expediente.

Imagina que eres un usuario que tiene la versión M de un SPA cargada en tu navegador:

  1. Su canalización de CD implementa la nueva versión N de la aplicación en el servidor
  2. Navega dentro del SPA, que envía un XHR al servidor para obtener /some.template
    • (Su navegador no ha actualizado la página, por lo que aún está ejecutando la versión M )
  3. El servidor responde con el contenido de /some.template . ¿Desea que devuelva la versión M o N de la plantilla?

Si el formato de /some.template cambió entre las versiones M y N (o se cambió el nombre del archivo o lo que sea), es probable que no desee que la versión N de la plantilla se envíe al navegador que ejecuta la versión anterior M del analizador . †

Las aplicaciones web se encuentran con este problema cuando se cumplen dos condiciones:

  • Los recursos se solicitan de forma asíncrona en algún momento después de la carga de la página inicial
  • La lógica de la aplicación asume cosas (que pueden cambiar en futuras versiones) sobre el contenido del recurso

Una vez que su aplicación necesita presentar varias versiones en paralelo, resolver el almacenamiento en caché y la "recarga" se vuelve trivial:

  1. Instale todos los archivos del sitio en /v<release_tag_1>/…files… versionadas: /v<release_tag_1>/…files… , /v<release_tag_2>/…files…
  2. Establece los encabezados HTTP para permitir que los navegadores guarden los archivos para siempre
    • (O mejor aún, poner todo en un CDN)
  3. Actualice todas las etiquetas <script> y <link> , etc. para que apunten a ese archivo en uno de los directorios versionados

El último paso parece complicado, ya que podría requerir llamar a un creador de URL para cada URL en su código del lado del servidor o del lado del cliente. O simplemente puede hacer un uso inteligente de la etiqueta <base> y cambiar la versión actual en un solo lugar.

† Una forma de evitar esto es ser agresivo al forzar al navegador a recargar todo cuando se lanza una nueva versión. Pero para permitir que se completen las operaciones en curso, puede ser más fácil admitir al menos dos versiones en paralelo: v-current y v-previous.


No estoy seguro de por qué están teniendo tanto dolor al implementar esta solución.

Todo lo que debe hacer si obtiene la marca de tiempo modificada del archivo y la agrega como una cadena de consulta al archivo

En PHP lo haría como:

<link rel="stylesheet" href="mycss.css?v=<?php echo filemtime(''mycss.css'') ?>"/>

filemtime es una función de PHP que devuelve la marca de tiempo modificada del archivo.


No se ha encontrado el enfoque DOM del lado del cliente creando dinámicamente el elemento nodo de script (o css):

<script> var node = document.createElement("script"); node.type = "text/javascript"; node.src = ''test.js?''+Math.floor(Math.random()*999999999); document.getElementsByTagName("head")[0].appendChild(node); </script>


Para ASP.NET 4.5 y versiones posteriores, puede utilizar la agrupación de scripts .

La solicitud es http://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81 AllMyScripts. La cadena de consulta v tiene un token de valor que es un identificador único utilizado para el almacenamiento en caché. Mientras el paquete no cambie, la aplicación ASP.NET solicitará el paquete AllMyScripts usando este token. Si cualquier archivo en el paquete cambia, el marco de optimización ASP.NET generará un nuevo token, garantizando que las solicitudes del paquete para el navegador obtendrán el paquete más reciente.

Hay otros beneficios de la agrupación que incluyen un mayor rendimiento en la primera carga de páginas con minificación.


Para ASP.NET supongo que la próxima solución con opciones avanzadas (modo debug / release, versiones):

Js o archivos css incluidos por tal forma:

<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" /> <link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />

Global.JsPostfix y Global.CssPostfix se calculan de la siguiente manera en Global.asax:

protected void Application_Start(object sender, EventArgs e) { ... string jsVersion = ConfigurationManager.AppSettings["JsVersion"]; bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]); int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision; JsPostfix = ""; #if !DEBUG JsPostfix += ".min"; #endif JsPostfix += ".js?" + jsVersion + "_" + buildNumber; if (updateEveryAppStart) { Random rand = new Random(); JsPosfix += "_" + rand.Next(); } ... }


Publicación interesante. Habiendo leído todas las respuestas aquí combinadas con el hecho de que nunca he tenido ningún problema con cadenas de consulta "falsas" (lo cual no estoy seguro de por qué todos son tan reacios a usar esto), creo que la solución (que elimina la necesidad de reglas de reescritura de apache). como en la respuesta aceptada) es calcular un corto HASH del contenido del archivo CSS (en lugar de la fecha y hora del archivo) como una cadena de consulta falsa.

Esto daría lugar a lo siguiente:

<link rel="stylesheet" href="/css/base.css?[hash-here]" type="text/css" />

Por supuesto, las soluciones de datetime también hacen el trabajo en el caso de editar un archivo CSS, pero creo que se trata del contenido del archivo css y no del datetime del archivo, así que, ¿por qué confundirse?


Puede forzar un "almacenamiento en caché de toda la sesión" si agrega el id de sesión como un parámetro espumoso del archivo js / css:

<link rel="stylesheet" src="myStyles.css?ABCDEF12345sessionID" /> <script language="javascript" src="myCode.js?ABCDEF12345sessionID"></script>

Si desea un almacenamiento en caché de toda la versión, puede agregar algún código para imprimir la fecha del archivo o similar. Si está utilizando Java, puede usar una etiqueta personalizada para generar el enlace de una manera elegante.

<link rel="stylesheet" src="myStyles.css?20080922_1020" /> <script language="javascript" src="myCode.js?20080922_1120"></script>


Simplemente puede agregar un número aleatorio con la URL de CSS / JS como

example.css?randomNo=Math.random()


Simplemente puedes poner ?foo=1234 al final de tu importación de css / js, cambiando 1234 para que sea lo que quieras. Echa un vistazo a la fuente SO HTML para ver un ejemplo.

La idea es que el? Los parámetros se descartan / ignoran en la solicitud de todos modos y puede cambiar ese número cuando despliegue una nueva versión.

Nota: existe algún argumento con respecto a cómo afecta esto exactamente al almacenamiento en caché. Creo que la idea general es que las solicitudes GET, con o sin parámetros, deben poder ser almacenadas en caché, por lo que la solución anterior debería funcionar.

Sin embargo, depende del servidor web decidir si desea adherirse a esa parte de la especificación y al navegador que usa el usuario, ya que puede seguir adelante y solicitar una versión nueva de todos modos.


Actualización: Reescrito para incorporar sugerencias de John Millikin y da5id . Esta solución está escrita en PHP, pero debe adaptarse fácilmente a otros idiomas.

Actualización 2: Incorporación de comentarios de Nick Johnson de que la expresión regular .htaccess puede causar problemas con archivos como json-1.3.js . La solución es solo volver a escribir si hay exactamente 10 dígitos al final. (Debido a que 10 dígitos cubren todas las marcas de tiempo del 9/9/2001 al 11/20/2286).

Primero, usamos la siguiente regla de reescritura en .htaccess:

RewriteEngine on RewriteRule ^(.*)/.[/d]{10}/.(css|js)$ $1.$2 [L]

Ahora, escribimos la siguiente función de PHP:

/** * Given a file, i.e. /css/base.css, replaces it with a string containing the * file''s mtime, i.e. /css/base.1221534296.css. * * @param $file The file to be loaded. Must be an absolute path (i.e. * starting with slash). */ function auto_version($file) { if(strpos($file, ''/'') !== 0 || !file_exists($_SERVER[''DOCUMENT_ROOT''] . $file)) return $file; $mtime = filemtime($_SERVER[''DOCUMENT_ROOT''] . $file); return preg_replace(''{//.([^./]+)$}'', ".$mtime./$1", $file); }

Ahora, donde sea que incluyas tu CSS, cámbiala desde esto:

<link rel="stylesheet" href="/css/base.css" type="text/css" />

A esto:

<link rel="stylesheet" href="<?php echo auto_version(''/css/base.css''); ?>" type="text/css" />

De esta manera, nunca más tendrá que modificar la etiqueta de enlace, y el usuario siempre verá la última CSS. El navegador podrá almacenar en caché el archivo CSS, pero cuando realice cambios en su CSS, el navegador lo verá como una nueva URL, por lo que no utilizará la copia en caché.

Esto también puede funcionar con imágenes, favicons y JavaScript. Básicamente todo lo que no se genera dinámicamente.


Técnica simple del lado del cliente

En general, el almacenamiento en caché es bueno ... Así que hay un par de técnicas, dependiendo de si está solucionando el problema por sí mismo a medida que desarrolla un sitio web, o si está tratando de controlar el caché en un entorno de producción.

Los visitantes generales de su sitio web no tendrán la misma experiencia que usted tiene cuando desarrolla el sitio. Dado que el visitante promedio llega al sitio con menos frecuencia (tal vez solo unas pocas veces al mes, a menos que sea una red de Google o hi5), es menos probable que tengan sus archivos en caché, y eso puede ser suficiente. Si desea forzar una nueva versión en el navegador, siempre puede agregar una cadena de consulta a la solicitud y aumentar el número de versión cuando realice cambios importantes:

<script src="/myJavascript.js?version=4"></script>

Esto asegurará que todos obtengan el nuevo archivo. Funciona porque el navegador mira la URL del archivo para determinar si tiene una copia en caché. Si su servidor no está configurado para hacer nada con la cadena de consulta, se ignorará, pero el nombre se verá como un nuevo archivo para el navegador.

Por otro lado, si está desarrollando un sitio web, no desea cambiar el número de versión cada vez que guarde un cambio en su versión de desarrollo. Eso sería tedioso.

Así que mientras desarrolla su sitio, un buen truco sería generar automáticamente un parámetro de cadena de consulta:

<!-- Development version: --> <script>document.write(''<script src="/myJavascript.js?dev='' + Math.floor(Math.random() * 100) + ''"/><//script>'');</script>

Agregar una cadena de consulta a la solicitud es una buena manera de crear una versión de un recurso, pero para un sitio web simple puede ser innecesario. Y recuerda, el almacenamiento en caché es algo bueno.

También vale la pena señalar que el navegador no es necesariamente mezquino para mantener los archivos en caché. Los navegadores tienen políticas para este tipo de cosas y, por lo general, cumplen con las reglas establecidas en la especificación HTTP. Cuando un navegador realiza una solicitud a un servidor, parte de la respuesta es un encabezado de CADUCOS ... una fecha que le dice al navegador cuánto tiempo debe mantenerse en el caché. La próxima vez que el navegador encuentre una solicitud para el mismo archivo, verá que tiene una copia en caché y mira a la fecha de CADUCOS para decidir si se debe usar.

Lo creas o no, en realidad es tu servidor el que hace que la memoria caché del navegador sea tan persistente. Podría ajustar la configuración de su servidor y cambiar los encabezados de CADUCOS, pero la pequeña técnica que he escrito anteriormente es probablemente una forma mucho más sencilla de hacerlo. Dado que el almacenamiento en caché es bueno, por lo general, desea establecer esa fecha en el futuro (un "Encabezado que vence en el futuro lejano"), y utilizar la técnica descrita anteriormente para forzar un cambio.

Si está interesado en obtener más información sobre HTTP o sobre cómo se realizan estas solicitudes, un buen libro es "Sitios web de alto rendimiento" de Steve Souders. Es una muy buena introducción al tema.


Lo siento por traer de vuelta un hilo muerto.

@ TomA tiene razón.

El uso del método de "cadena de consulta" no se almacenará en caché según lo citado por Steve Souders a continuación:

... ese Squid, un proxy popular, no almacena en caché los recursos con una cadena de consulta.

TomA sugerencia de @ TomA de usar style.TIMESTAMP.css es buena, pero el MD5 sería mucho mejor ya que solo cuando los contenidos fueron realmente modificados, el MD5 también cambia.


Para mi desarrollo, encuentro que Chrome tiene una gran solución.

https://developer.chrome.com/devtools/docs/tips-and-tricks#hard-reload

Con las herramientas para desarrolladores abiertas, simplemente haga clic en el botón de actualización y suéltelo una vez que pase el mouse sobre "Vaciar caché y recargar duro".

¡Este es mi mejor amigo, y es una forma súper liviana de obtener lo que deseas!


Parece que todas las respuestas aquí sugieren algún tipo de control de versiones en el esquema de nombres, que tiene sus desventajas.

Los navegadores deben saber qué almacenar en caché y qué no guardar en caché leyendo la respuesta de los servidores web, en particular los encabezados http: ¿durante cuánto tiempo es válido este recurso? ¿Se actualizó este recurso desde la última vez que lo recuperé? etcétera.

Si las cosas están configuradas ''correctamente'', solo actualizar los archivos de su aplicación debería (en algún momento) actualizar los cachés de los navegadores. Por ejemplo, puede configurar su servidor web para decirle al navegador que nunca almacene en caché los archivos (lo cual es una mala idea).

Una explicación más detallada de cómo funciona eso está aquí https://www.mnot.net/cache_docs/#WORK


Sugiero implementar el siguiente proceso:

  • versione sus archivos css / js cada vez que implemente, algo como: screen.1233.css (el número puede ser su revisión de SVN si usa un sistema de control de versiones)

  • Minificarlos para optimizar los tiempos de carga.


Estoy agregando esta respuesta como una respuesta específica de SilverStripe http://www.silverstripe.org que estaba buscando y que nunca encontré, pero he encontrado en la lectura: http://api.silverstripe.org/3.0/source-class-SS_Datetime.html#98-110

Esperamos que esto ayude a alguien a usar una plantilla SilverStripe y tratar de forzar la recarga de una imagen en caché en cada visita / actualización de la página. En mi caso, es una animación gif que solo se reproduce una vez y, por lo tanto, no se reproduce después de que se almacenó en caché. En mi plantilla simplemente agregué:

?$Now.Format(dmYHis)

hasta el final de la ruta del archivo para crear una marca de tiempo única y forzar al navegador a tratarla como un nuevo archivo.


Google Chrome tiene la opción Recargar duro , así como la opción Vaciar caché y Recargar duro . Puede hacer clic y mantener presionado el botón de recargar (en el modo Inspección) para seleccionar uno.


Para un entorno Java Servlet, puede mirar la biblioteca Jawr . La página de características explica cómo maneja el almacenamiento en caché:

Jawr hará todo lo posible para obligar a sus clientes a almacenar en caché los recursos. Si un navegador pregunta si un archivo cambió, se envía un encabezado 304 (no modificado) sin contenido. Por otro lado, con Jawr estará 100% seguro de que todos los clientes descargan nuevas versiones de sus paquetes. Cada URL a sus recursos incluirá un prefijo basado en contenido, generado automáticamente, que cambia automáticamente cada vez que se actualiza un recurso. Una vez que implemente una nueva versión, la URL del paquete también cambiará, por lo que será imposible que un cliente use una versión anterior en caché.

La biblioteca también realiza la reducción de js / css, pero puede desactivarlo si no lo desea.


Puse un hash MD5 del contenido del archivo en su URL. De esa manera puedo establecer una fecha de vencimiento muy larga, y no tengo que preocuparme por los usuarios que tienen JS o CSS antiguos.

También calculo esto una vez por archivo en tiempo de ejecución (o en los cambios del sistema de archivos) para que no haya nada divertido que hacer en el momento del diseño o durante el proceso de compilación.

Si está utilizando ASP.NET MVC, puede consultar el código en mi otra respuesta aquí .


Recientemente resolví esto usando Python. Aquí el código (debería ser fácil de adoptar a otros idiomas):

def import_tag(pattern, name, **kw): if name[0] == "/": name = name[1:] # Additional HTML attributes attrs = '' ''.join([''%s="%s"'' % item for item in kw.items()]) try: # Get the files modification time mtime = os.stat(os.path.join(''/documentroot'', name)).st_mtime include = "%s?%d" % (name, mtime) # this is the same as sprintf(pattern, attrs, include) in other # languages return pattern % (attrs, include) except: # In case of error return the include without the added query # parameter. return pattern % (attrs, name) def script(name, **kw): return import_tag("""<script type="text/javascript" """ +/ """ %s src="/%s"></script>""", name, **kw) def stylesheet(name, **kw): return import_tag(''<link rel="stylesheet" type="text/css" '' +/ """%s href="/%s">'', name, **kw)

Este código básicamente agrega la marca de tiempo de los archivos como un parámetro de consulta a la URL. La llamada de la siguiente función.

script("/main.css")

resultará en

<link rel="stylesheet" type="text/css" href="/main.css?1221842734">

La ventaja, por supuesto, es que nunca tendrá que cambiar su html nuevamente, al tocar el archivo CSS se activará automáticamente una invalidación de caché. Funciona muy bien y la sobrecarga no se nota.