web-dev-qa-db-fra.com

Cache de cache via params

Nous voulons mettre en cache les déploiements de production, mais ne perdons pas beaucoup de temps à chercher un système pour le faire. Je pensais appliquer un paramètre à la fin des fichiers css et js avec le numéro de version actuel:

<link rel="stylesheet" href="base_url.com/file.css?v=1.123"/>

Deux questions: cela va-t-il effectivement casser la cache? Le paramètre amènera-t-il alors le navigateur à ne jamais mettre en cache la réponse de cette URL, car il indique qu'il s'agit d'un contenu dynamique?

103
Brad Herman

Le paramètre ?v=1.123 indique une chaîne de requête et le navigateur pensera donc qu'il s'agit d'un nouveau chemin d'accès, par exemple, ?v=1.0. Ainsi, il se charge à partir du fichier, pas du cache. Comme tu veux. 

Et, le navigateur supposera que la source restera la même lors de votre prochain appel à ?v=1.123 et should le cache avec cette chaîne. Ainsi, il restera mis en cache, quelle que soit la configuration de votre serveur, jusqu'à ce que vous passiez à ?v=1.124 ou à un autre.

98
Marshall

Deux questions: cela va-t-il effectivement casser la cache? 

Oui. Même Stack Overflow utilise cette méthode, bien que je me souvienne qu’ils (avec leurs millions de visiteurs par jour et leurs millions de versions et de configurations de clients et de mandataires différentes) ont eu des cas bizarres où Edge cache. Mais l'hypothèse générale est que cela fonctionnera et constitue une méthode appropriée pour casser la mise en cache sur les clients.

Le paramètre amènera-t-il alors le navigateur à ne jamais mettre en cache la réponse de cette URL, car il indique qu'il s'agit d'un contenu dynamique?

Non, le paramètre ne changera pas la politique de mise en cache. les en-têtes de mise en cache envoyés par le serveur s'appliquent toujours et, s'il n'en envoie pas, les paramètres par défaut du navigateur. 

35
Pekka 웃

Il est plus sûr de mettre le numéro de version dans le nom de fichier réel. Cela permet à plusieurs versions d'exister en même temps afin que vous puissiez déployer une nouvelle version. S'il existe toujours des pages HTML en cache qui demandent l'ancienne version, elles obtiendront la version qui fonctionne avec leur code HTML.

Notez que dans l'un des plus grands déploiements versionnés sur Internet, jQuery utilise des numéros de version dans le nom de fichier actuel et permet en toute sécurité la coexistence de plusieurs versions sans aucune logique spéciale côté serveur (chaque version n'est qu'un fichier différent).

Cela masque le cache une fois lorsque vous déployez de nouvelles pages et de nouveaux fichiers liés (comme vous le souhaitez) et que ces versions peuvent ensuite être mises en cache (ce que vous souhaitez également).

21
jfriend00

Une fois que le client a téléchargé la ressource, il décompose le cache une fois que toutes les autres réponses sont fournies depuis le cache du client, sauf si:

  1. le paramètre v est mis à jour.
  2. le client efface son cache
9
ncremins

Comme d'autres l'ont déjà dit, le contournement du cache avec un paramètre de requête est généralement considéré comme une mauvaise idée (tm), et ce depuis longtemps. Il est préférable de refléter la version dans le nom du fichier. Html5 Boilerplate déconseillé en utilisant la chaîne de requête, entre autres.

Cela dit, parmi les recommandations que j'ai vues qui ont cité une source, toutes semblent tirer leur sagesse d'un article de 2008 de Steve Souders. Ses conclusions sont basées sur le comportement des mandataires à l'époque, et ils peuvent ou non être pertinents de nos jours. Néanmoins, en l’absence d’informations plus récentes, le changement de nom de fichier est l’option sûre.

9
hashchange

En général, cela devrait suffire, mais il est possible que cela ne fonctionne pas s'il existe un cache intermédiaire (un proxy) configuré pour ignorer les paramètres de la requête.

Par exemple, si vous diffusez du contenu statique via le CDN Akamai, il peut être configuré pour ignorer les paramètres de requête afin d'empêcher le contournement du cache à l'aide de cette méthode.

6
Ken Liu

Tout dépend de la robustesse que vous souhaitez pour votre mise en cache. Par exemple, le serveur proxy squid (et éventuellement d’autres) par défaut et non en cache URL servies avec une chaîne de requête - au moins, il l'a fait quand cet article a été écrit. Si certains cas d’utilisation entraînant des erreurs inutiles dans le cache ne vous dérangent pas, continuez avec les paramètres de requête. Mais il est très facile de configurer un schéma de contournement de cache basé sur le nom de fichier qui évite ce problème.

5
Bobby Jack

Trouvé une comparaison des 2 techniques (chaîne de requête vs nom de fichier) ici

La version en tant que chaîne de requête pose deux problèmes. 

Premièrement, il se peut que ce ne soit pas toujours un navigateur qui implémente la mise en cache à travers laquelle nous devons nous séparer. On dit que certains mandataires (peut-être plus anciens) ignorent la chaîne de requête en ce qui concerne leur comportement de mise en cache.

Deuxièmement, dans certains scénarios de déploiement plus complexes, dans lesquels vous avez plusieurs serveurs frontaux et/ou multiples, une mise à niveau est tout sauf instantanée. Vous devez pouvoir servir à la fois l'ancienne et la nouvelle version de vos actifs. Voyez par exemple comment cela vous affecte lorsque vous utilisez Google App Engine.

5
user

Une autre approche similaire consiste à utiliser htaccessmod_rewrite pour ignorer une partie du chemin lors du traitement des fichiers. Votre page d'indexation jamais mise en cache fait référence au dernier chemin d'accès aux fichiers. 

Du point de vue du développement, il est aussi simple d’utiliser des paramètres pour le numéro de version, mais c’est aussi robuste que le nom de fichier.

Utilisez la partie ignorée du chemin d'accès au numéro de version, le serveur l'ignorant simplement et servant le fichier non mis en cache. 

1.2.3/css/styles.css sert le même fichier que css/styles.css puisque le premier répertoire est vidé et ignoré par le fichier htaccess

Y compris les fichiers versionnés

<?php
  $version = "1.2.3";
?>

<html>
  <head>
    <meta http-equiv="cache-control" content="max-age=0" />
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="expires" content="0" />
    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
    <meta http-equiv="pragma" content="no-cache" />
    <link rel="stylesheet" type="text/css" href="<?php echo $version ?>/css/styles.css">
  </head>
  <body>
    <script src="<?php echo $version ?>/js/main.js"></script>
  </body>
</html>

Notez que cette approche signifie que vous devez désactiver la mise en cache de votre page d'index - Vous utilisez des balises <meta> pour désactiver la mise en cache dans tous les navigateurs?

fichier .htaccess

RewriteEngine On

# if you're requesting a file that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-f 
# likewise if a directory that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-d 

# otherwise, rewrite foo/bar/baz to bar/baz - ignore the first directory
RewriteRule ^[^/]+/(.+)$ $1 [L] 

Vous pouvez adopter la même approche sur n’importe quelle plate-forme de serveur permettant la réécriture d’URL.

(condition de réécriture adaptée de mod_rewrite - répertoire de réécriture pour interroger la chaîne, sauf/#!/ )

... et si vous avez besoin de contourner le cache pour votre page d’entrée d’index/site, vous pouvez toujours utiliser JavaSript pour l’actualiser. 

4
alexanderbird
<script type="text/javascript">
// front end cache bust

var cacheBust = ['js/StrUtil.js', 'js/protos.common.js', 'js/conf.js', 'bootstrap_ECP/js/init.js'];   
for (i=0; i < cacheBust.length; i++){
     var el = document.createElement('script');
     el.src = cacheBust[i]+"?v=" + Math.random();
     document.getElementsByTagName('head')[0].appendChild(el);
}
</script> 
2
Conete Cristian

J'espère que cela vous aidera à injecter un fichier JS externe

<script type="text/javascript"> 
var cachebuster = Math.round(new Date().getTime() / 1000); 
document.write('<scr'+'ipt type="text/javascript" src="external.js?cb=' +cachebuster+'"></scr' + 'ipt>');
</script>

Source - code Cachebuster en JavaScript

0
Vinit Kadkol
 <script>
    var storedSrcElements = [
         "js/exampleFile.js",
         "js/sampleFile.js",
         "css/style.css"
          ];

    var head= document.getElementsByTagName('head')[0];
    var script;
    var link;
    var versionNumberNew = 4.6;

    for(i=0;i<storedSrcElements.length;i++){
     script= document.createElement('script');
     script.type= 'text/javascript';
     script.src= storedSrcElements[i] + "?" + versionNumberNew;
     head.appendChild(script);
    }     


     </script> 


       ### Change the version number  (versionNumberNew) when you want the new files to be loaded  ###
0
Teja