31

Últimamente me he visto con muchos problemas en Google Chrome (en otros navegadores me va bien, exceptuando también Safari en Mac) al momento de cargar una nueva versión de una hoja de estilos (.css) o un script javascript (.js), pensé que podía solucionarlo mediante un simple:

<link rel="stylesheet" href="/private/css/visual.css?v=1" />
<script src="/private/js/visual.js?v=1"></script>

Pero no me funciona siempre y tengo que estar cambiando el valor de v=1 constatemente para que cargue las nuevas versiones de los respectivos archivos

¿Hay alguna forma de prevenir la caché correctamente?

Sease con una librería, código nativo javascript, algo que añadir a mis archivos .css o .js, cambiar en mi servidor, cambiar en mi maquina, configuraciones de navegadores, etc... y evitar este problema.

NOTA: La caché permanece tanto de manera local como ya alojado en un servidor / dominio

ACTUALIZACIÓN: Quizá al principio no fui muy claro, aunque las respuesta de JuankGlezz y derivadas me ayudan a mi en el entorno de desarrollo busco una respuesta que pueda servir para mis usuarios finales sin que ellos no tengan que tocar nada...

Jorius
  • 6,109
  • 9
  • 28
  • 55
  • 2
    En Chrome, con las herramientas de desarrollador abiertas, deja pulsado el botón de recarga durante un segundo y te aparecen diferentes modos de recarga, selecciona uno que es "vaciar caché y recargar" – Alvaro Montoro Apr 18 '17 at 21:39
  • 1
    @AlvaroMontoro o bien clic derecho y aparecen las opciones, claramente con las herramientas de desarrollador abiertas – JuankGlezz Apr 19 '17 at 05:36
  • @Jorius aunado a tu solución de archivos, ¿utilizas en conjunto algún lenguaje como PHP, C# con Asp.Net, Java etc? De ser así, sería mucho más sencillo encontrar un número random para concatenarlo a la referencia de archivo de Javascript o CSS, así como lo expongo en [mi respuesta](https://es.stackoverflow.com/a/63815/16841) – Phi Apr 20 '17 at 20:42
  • @Flxtr utilizo HTML + CSS + JS + PHP en un servidor Apache – Jorius Apr 20 '17 at 20:43
  • 2
    Jorius La respuesta de @JuankGlezz (al menos la primera parte) no es una solución únicamente para ti mientras desarrollas. Es válida para producción, con el problema evidente del impacto que tiene el desactivar la caché desde el servidor. Ojo con eso. – frikinside Apr 21 '17 at 11:34

8 Answers8

23

Esto se puede usar en entornos de producción y en depuración, si eres de los que modifican constantemente los SCRIPT y los CSS de las paginas web, pero no sueles mantener la consola del navegador abierta y quieres evitar la cache, puedes añadir las siguientes lineas en el HTML.

<head>
  <meta http-equiv="Expires" content="0">
  <meta http-equiv="Last-Modified" content="0">
  <meta http-equiv="Cache-Control" content="no-cache, mustrevalidate">
  <meta http-equiv="Pragma" content="no-cache">
</head>

En WordPress, para añadir etiquetas en el </head> debemos editar la plantilla o theme, concretamente debemos editar el archivo header.php donde se encuentran las etiquetas <head> y </head>.

En una aplicación desarrollada en PHP se puede forzar a que no guarde cache en el navegador, se pueden usar las siguientes lineas:

<?php
  header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
  header("Expires: Sat, 1 Jul 2000 05:00:00 GMT"); // Fecha en el pasado
?>

Si eres desarrollador y no quisieras agregar las lineas anteriores puedes evitar la cache desde consola del navegador (F12).

Es recomendado mantener la la consola del navegador abierta (F12) y habilitar la casilla de disable cache en la solapa de network

habilitar la casilla de disable cache en la solapa de network

Para Firefox abrir la consola de depurador (F12)

  1. nos vamos a opciones de la caja de herramientas
  2. buscamos desactivar el cache http

habilitar la casilla de disable cache en Firefox

Nota:

Para esto debe estar siempre abierta la consola (F12) de lo contrario seguirá guardando la cache tanto para Google Chrome como Mozilla Firefox.
Lo mas recomendado en el ámbito de depuración es abrir una ventana en modo incógnito.

JuankGlezz
  • 5,398
  • 8
  • 28
  • 57
  • Si se desactiva el cache de forma permanente, no afectaria el rendimiento del sitio? – Tecnologer Apr 21 '17 at 00:14
  • @Tecnologer si, porque es volver a cargar un archivo desde el servidor cada que actualice la pagina o la carge, el cache es para evitar volver a cargar el archivo y mantener el archivo por un tiempo determinado así puede mejorar la carga de la pagina – JuankGlezz Apr 21 '17 at 03:41
21

Una forma es que cuando hagas la referencia a los archivos de JavaScript pongas al final ?1, Esto significa que el ?1 es un tipo de versionado del archivo para que el navegador lo vuelva a cargar nuevamente y no cargue los archivos que se encuentran almacenados en caché. Por ejemplo:

<script type="text/javascript"
    src="http://sitio.com/jsFiles/miArchivoJavaScript.js?123">
</script>

Lo recomendable, es tener algún tipo de función para que después del sigo de interrogación generé un número al azar.

La ventaja de utilizar esta funcionalidad es que no requiere intervención del usuario.

Actualización

Dado que utilizas una solución en PHP, lo mejor sería generar un número dinámico a la versión del archivo JavaScript o CSS para asegurar que el archivo siempre sea cargado del servidor y no del caché del navegador utilizando la función rand() para generar un número aleatorio.

Por ejemplo:

<link rel="stylesheet" href="/private/css/visual.css?v=<?php echo(rand()); ?>" />
<script src="/private/js/visual.js?v=<?php echo(rand()); ?>"></script>
Phi
  • 9,913
  • 5
  • 25
  • 47
4

Puedes probar de esta forma si tu archivo tiene extensión .php:

<script type="text/javascript"
 src="http://sitio.com/jsFiles/miArchivoJavaScript.js?v=<?php echo time();?>">
 </script>

Y si lo deseas hacer desde JS, tal vez algo asi simple ayudaria:

var js = document.querySelectorAll('script');

for (var i = 0; i < js.length; i++) {
    js[i].src = js[i].src + '?v=' + Date.now();
}

var css = document.querySelectorAll('link');

for (var i = 0; i < css.length; i++) {
    css[i].href = css[i].href + '?v=' + Date.now();
}

Solo recuerda que si usas el codigo JS, tus archivos JS o CSS se deberian cargar primero, para luego inmediatamente actualizar el atributo src o href.

kip
  • 241
  • 1
  • 5
1

Si siempre quieres evitar el caché, podrías hacer:

<script type="text/javascript">
  var estilos = 'carpeta/css/style.css?' + Math.random();
</script>

<script type="text/javascript">
  document.write('<link href="' + estilos + '" rel="stylesheet">');
</script>

O sino de forma dinámica realizar la referencia, recuerda que la variable estilos podría ser una colección de cadenas.

Davlio
  • 2,900
  • 1
  • 13
  • 22
0

Lo que yo hago es lo siguiente:

Verifico que no hallan errores en el código.

Utilizo la combinación Control + shift + R

Abro la consola y paso al apartado network , seguido pulso F5 para ver si se importan los archivos correctamente.

Dev 200
  • 5,246
  • 5
  • 39
  • 80
0

Otra forma de evitar el cache de por ejemplo tu css o js , sería modificando el .htaccess de tu apache, esto para evitar que se aloje en cache o limitar el tiempo de vida, esto te ayudaría para que cada menor tiempo se descarguen tus js y css status code = 200 y no 304 que es el que recibe cuando el recurso ya esta en cache.

<IfModule mod_expires.c> 
      ExpiresActive On
      ExpiresDefault "access plus 1 seconds"
      ExpiresByType text/html "access plus 1 seconds"
      ExpiresByType image/x-icon "access plus 2592000 seconds"
      ExpiresByType image/gif "access plus 2592000 seconds"
      ExpiresByType image/jpeg "access plus 2592000 seconds"
      ExpiresByType image/png "access plus 2592000 seconds"
      ExpiresByType text/css "access plus 604800 seconds"
      ExpiresByType text/javascript "access plus 86400 seconds"
      ExpiresByType application/x-javascript "access plus 86400 seconds"
</IfModule>

o

<FilesMatch "\.(?i:gif|jpe?g|png|ico|css|js|swf)$">

  <IfModule mod_headers.c>
    Header set Cache-Control "max-age=172800, public, must-revalidate"
  </IfModule>

</FilesMatch>
Ventur
  • 1,778
  • 11
  • 25
0

Si usas un servidor apache en linux puedes hacer lo siguiente:

activar mod_expire:

    $ sudo a2enmod expires

modificar el archivo /etc/apache2/apache2.conf y agregar lo siguiente:

    <IfModule mod_expires.c>
     ExpiresActive On
     #ExpiresDefault "access plus 1 year"    # activar para servidor en producción
     ExpiresDefault "access plus 1 seconds" # activar para servidor en desarrollo
    </IfModule>

Luego reiniciar el servidor apache:

    $ sudo service apache2 restart

con esto debe resolver el cache en el cliente. sin embargo debes tener en cuenta que en un servidor en producción debes aumentar el valor para la variable ExpiresDefault.

fwBasic
  • 2,776
  • 1
  • 10
  • 22
0

Otra opción que podrías aplicar es versionar automáticamente tus archivos CSS y JS.

OPCIÓN 1:

Agregar la versión (ej: fecha de última modificación del archivo) como variable al path del mismo.

Así:

  1. Creamos una función que obtenga la fecha de última modificación (eg: filemtime) del archivo y la concatene como variable al path.

    <?php
    function autoVer($url)
    {
      $path = pathinfo($url);
      $ver = '?v='.filemtime($_SERVER['DOCUMENT_ROOT'].$url);
      return $path['dirname'].'/'.$path['basename'].$ver;
    }
    ?>
    
  2. Luego invocamos esta función sobre los archivos a versionar.

    <link rel="stylesheet" href="<?php echo autoVer('/private/css/visual.css'); ?>" />
    <script src="<?php echo autoVer('/private/js/visual.js'); ?>"></script>
    

El resultado sería algo así:

<link rel="stylesheet" href="/private/css/visual.css?v=1492816098" />
<script src="/private/js/visual.js?v=1492816000"></script>

OPCION 2

Suponiendo que la opción 1 "no siempre te funcione", y siguiendo la misma línea, podemos agregar la versión como parte del nombre del archivo y mediante un .htaccess reescribir el path de estos.

Así:

  1. Creamos una función que obtenga la fecha de última modificación (eg: filemtime) del archivo y la incluya como parte del nombre del archivo.

    <?php
    function autoVer($url)
    {
      $path = pathinfo($url);
      $ver = '.'.filemtime($_SERVER['DOCUMENT_ROOT'].$url).'.';
      return $path['dirname'].'/'.str_replace('.', $ver, $path['basename']);
    }
    ?>
    
  2. Luego invocamos esta función sobre los archivos a versionar.

    <link rel="stylesheet" href="<?php echo autoVer('/private/css/visual.css'); ?>" />
    <script src="<?php echo autoVer('/private/js/visual.js'); ?>"></script>
    

    El resultado sería algo así:

    <link rel="stylesheet" href="/private/css/visual.1492816098.css" />
    <script src="/private/js/visual.1492816000.js"></script>
    
  3. Creamos un archivo .htaccess una regla para que traduzca estas "rutas"

    #Regla para archivos versionados
    RewriteRule ^(private/(js|css|imgs)/)(.+)\.(.+)\.(js|css|jpg|gif|png)$ $1$3.$5 [L]
    
Marcos
  • 30,626
  • 6
  • 28
  • 63