Forcer le navigateur à vider le cache

284

Existe-t-il un moyen de mettre du code sur ma page afin que lorsque quelqu'un visite un site, il vide le cache du navigateur, afin qu'il puisse voir les modifications?

Langages utilisés: ASP.NET, VB.NET, et bien sûr HTML, CSS et jQuery.

Adam
la source
Une bonne solution ou solution de contournement pour «vider le cache» peut être trouvée ici: stackoverflow.com/a/43676353/2008111
caramba

Réponses:

351

Si cela est sur le point .csset .jschange, une façon consiste à "écraser le cache" en ajoutant quelque chose comme " _versionNo" au nom du fichier pour chaque version. Par exemple:

script_1.0.css // This is the URL for release 1.0
script_1.1.css // This is the URL for release 1.1
script_1.2.css // etc.

Ou bien faites-le après le nom du fichier:

script.css?v=1.0 // This is the URL for release 1.0
script.css?v=1.1 // This is the URL for release 1.1
script.css?v=1.2 // etc.

Vous pouvez consulter ce lien pour voir comment cela pourrait fonctionner.

Fermin
la source
10
C'est une assez bonne solution, et peut même être automatisée par votre système de construction (et devrait l'être). Stackoverflow, par exemple, utilise cette approche.
derobert
7
SO utilise maintenant des arguments GET.
Saeb Amini
60
Mieux encore est de conserver le nom de fichier tel quel, mais ajoutez le numéro de version comme paramètre de chaîne de requête, c'est-à-dire script.js?v=1.2. (Ou si vous ne suivez pas les versions, utilisez simplement l'heure de dernière modification du fichier, ce qui est encore plus facile à faire). Je ne sais pas si c'est ce que le commentateur précédent voulait dire!
Doin
5
Comment tout le monde fait cela avec le contrôle de version? On dirait une vraie douleur.
Shawn
1
@Shawn Contrôle de version: vous pouvez rendre les <link />balises de manière dynamique et injecter la version de l'application en tant que paramètre de chaîne de requête. Alternativement, certains CMS auront une "version des ressources client" en tant que paramètre à l'échelle du CMS qui est ajouté - l'administrateur du site peut augmenter manuellement ce numéro de version, et les mises à jour du CMS pourraient également le mettre à jour automatiquement. Conclusion: vous devez rendre les URL de fichier de manière dynamique.
Jeroen
103

Regardez dans le cache-contrôle et la balise META expire .

<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="EXPIRES" CONTENT="Mon, 22 Jul 2002 11:12:01 GMT">

Une autre pratique courante consiste à ajouter des chaînes en constante évolution à la fin des fichiers demandés. Par exemple:

<script type="text/javascript" src="main.js?v=12392823"></script>

Sampson
la source
44
Cela n'aidera pas beaucoup dans le cas où il est déjà mis en cache — puisque sa mise en cache, le serveur ne sera pas interrogé, et ne peut donc pas répondre sans no-cache. De plus, cette balise META ne devrait vraiment pas être utilisée, comme le dit la note, elle rompra avec les caches Web.
derobert
1
+1 ce que Derobert a dit. Il est toujours préférable d'utiliser les en-têtes HTTP pour suggérer une stratégie de cache aux clients et aux caches Web, mais même cela ne fonctionne pas pour forcer un rechargement du cache.
4
+1 pour votre deuxième solution. J'ai ce problème que le cache ne doit être effacé que la première fois après qu'un administrateur a effectué une mise à jour. Cette approche devrait résoudre cela
Jules Colle,
La désactivation complète du cache est généralement une très mauvaise idée.
Jordan
73

Mise à jour 2012

C'est une vieille question, mais je pense qu'elle a besoin d'une réponse plus à jour car il existe maintenant un moyen d'avoir plus de contrôle sur la mise en cache du site Web.

Dans les applications Web hors ligne (ce qui est vraiment n'importe quel site Web HTML5)applicationCache.swapCache() pouvez mettre à jour la version en cache de votre site Web sans avoir à recharger manuellement la page.

Voici un exemple de code du Guide du débutant pour l'utilisation du cache d'application sur HTML5 Rocks expliquant comment mettre à jour les utilisateurs vers la dernière version de votre site:

// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {

  window.applicationCache.addEventListener('updateready', function(e) {
    if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
      // Browser downloaded a new app cache.
      // Swap it in and reload the page to get the new hotness.
      window.applicationCache.swapCache();
      if (confirm('A new version of this site is available. Load it?')) {
        window.location.reload();
      }
    } else {
      // Manifest didn't changed. Nothing new to server.
    }
  }, false);

}, false);

Voir aussi Utilisation du cache d'application sur Mozilla Developer Network pour plus d'informations.

Mise à jour 2016

Les choses changent rapidement sur le Web. Cette question a été posée en 2009 et en 2012, j'ai publié une mise à jour sur une nouvelle façon de gérer le problème décrit dans la question. Quatre autres années se sont écoulées et il semble maintenant qu'il est déjà obsolète. Merci à cgaldiolo avoir signalé dans les commentaires.

Actuellement, depuis juillet 2016, la norme HTML, section 7.9, Applications Web hors ligne inclut un avertissement de dépréciation:

Cette fonctionnalité est en cours de suppression de la plateforme Web. (Il s'agit d'un long processus qui prend de nombreuses années.) L'utilisation de l'une des fonctionnalités de l'application Web hors ligne à l'heure actuelle est fortement déconseillée. Utilisez plutôt des travailleurs de service.

Il en va de même pour l' utilisation du cache d'application sur Mozilla Developer Network que j'ai référencé en 2012:

Obsolète
Cette fonctionnalité a été supprimée des normes Web. Bien que certains navigateurs puissent toujours le prendre en charge, il est en cours de suppression. Ne l'utilisez pas dans des projets anciens ou nouveaux. Les pages ou les applications Web qui l'utilisent peuvent se casser à tout moment.

Voir aussi Bogue 1204581 - Ajoutez un avis de dépréciation pour AppCache si l'interception de récupération par le technicien de service est activée .

rsp
la source
1
Cela implique-t-il que vous devez utiliser et gérer un fichier manifeste de cache?
Sam
Avertissement: l'interface du cache d'application (AppCache) est obsolète
cgaldiolo
59
Alors, quelle est la recommandation actuelle à partir de 2017?
Garrett
le principal problème que j'ai vu sur cette rubrique est lorsque le périphérique que le visualiseur utilise continue d'utiliser les versions mises en cache car la mémoire interne du périphérique des utilisateurs est saturée. il semble rester bloqué sur une version en cache de la page et ne mettra pas à jour les éléments du document. cela ne se produit-il qu'en chrome ?? c'est le seul navigateur sur lequel je l'ai vécu.
user2585548
4
2017: Utiliser des travailleurs de service.
digitai
27

Pas comme tel. Une méthode consiste à envoyer les en-têtes appropriés lors de la livraison de contenu pour forcer le navigateur à se recharger:

S'assurer qu'une page Web n'est pas mise en cache, dans tous les navigateurs.

Si votre recherche "cache header" ou quelque chose de similaire ici sur SO, vous trouverez des exemples spécifiques à ASP.NET.

Un autre moyen, moins propre mais parfois uniquement si vous ne pouvez pas contrôler les en-têtes côté serveur, consiste à ajouter un paramètre GET aléatoire à la ressource appelée:

myimage.gif?random=1923849839
Pekka
la source
2
Il est vraiment préférable de versionner correctement les fichiers. C'est un gaspillage assez important de bande passante et, probablement plus important encore, ralentit beaucoup votre site.
derobert
8
Cela dépend vraiment de la situation, n'est-ce pas? Si vous programmez un CMS et devez vous assurer que toutes les ressources modifiées sont correctement mises à jour, il est parfois impossible de contourner l'une de ces deux options.
Pekka
De telles solutions devraient être votées négativement. C'est à nous de limiter au maximum l'empreinte CO2 d'Internet.
chronométrage du
14

Pour les ressources statiques, la mise en cache correcte consisterait à utiliser des paramètres de requête avec la valeur de chaque déploiement ou version de fichier. Cela aura pour effet d'effacer le cache après chaque déploiement.

/Content/css/Site.css?version={FileVersionNumber}

Voici un exemple ASP.NET MVC.

<link href="@Url.Content("~/Content/Css/Reset.css")[email protected]().Assembly.GetName().Version" rel="stylesheet" type="text/css" />

N'oubliez pas de mettre à jour la version de l'assembly.

Paulius Zaliaduonis
la source
Merci pour cette réponse, mais comment faire cela lorsque nous ajoutons des ressources dans le BundleTable, s'il vous plaît?
toregua
Dans mon cas, cela renvoyait "0.0.0.0" comme version. Pour obtenir la version de la DLL de votre application MVC, utilisez-la à la place:[email protected]().Assembly.GetName().Version
CGodo
1
J'ai constaté que cela empêche Firefox et Chrome de mettre le contenu en cache.
Sam
10

J'ai eu un problème similaire et voici comment je l'ai résolu:

  1. Dans le index.htmlfichier, j'ai ajouté un manifeste:

    <html manifest="cache.manifest">
  2. Dans la <head>section inclus un script de mise à jour du cache:

    <script type="text/javascript" src="update_cache.js"></script>
  3. Dans la <body>section, j'ai inséré la fonction onload:

    <body onload="checkForUpdate()">
  4. Dans cache.manifestj'ai mis tous les fichiers que je veux mettre en cache. Il est important maintenant que cela fonctionne dans mon cas (Apache) juste en mettant à jour à chaque fois le commentaire "version". C'est aussi une option pour nommer les fichiers avec "? Ver = 001" ou quelque chose à la fin du nom mais ce n'est pas nécessaire . La modification # version 1.01déclenche simplement l' événement de mise à jour du cache.

    CACHE MANIFEST
    # version 1.01
    style.css
    imgs/logo.png
    #all other files

    Il est important d'inclure 1., 2. et 3. points uniquement dans index.html. Autrement

    GET http://foo.bar/resource.ext net::ERR_FAILED

    se produit car chaque fichier "enfant" essaie de mettre en cache la page alors que la page est déjà mise en cache.

  5. Dans le update_cache.jsfichier, j'ai mis ce code:

    function checkForUpdate()
    {
        if (window.applicationCache != undefined && window.applicationCache != null)
        {
            window.applicationCache.addEventListener('updateready', updateApplication);
        }
    }
    function updateApplication(event)
    {
        if (window.applicationCache.status != 4) return;
        window.applicationCache.removeEventListener('updateready', updateApplication);
        window.applicationCache.swapCache();
        window.location.reload();
    }

Maintenant, vous changez simplement les fichiers et dans le manifeste, vous devez mettre à jour le commentaire de la version. La page index.html va maintenant mettre à jour le cache.

Les parties de la solution ne sont pas les miennes, mais je les ai trouvées sur Internet et rassemblées pour que cela fonctionne.

Wojtek Mazurek
la source
Puis-je savoir où CACHE.MANIFEST est écrit.
Shweta Gulati
1
Shweta Gulati Le fichier manifeste doit se trouver dans le même dossier que le fichier "index". Quels sont les moments où cela ne fonctionne pas?
Wojtek Mazurek
1
@ShwetaGulati Oui, le cache ne détecte pas les changements dans les fichiers html - c'est pourquoi Vous devez mettre à jour le numéro de version dans le fichier manifeste, car c'est celui qui est en cours de vérification pour les changements. C'est vraiment difficile de vous aider, car je ne connais pas les détails. S'il vous plaît, dites-moi si vous avez mis tous les fichiers que vous souhaitez mettre en cache dans le manifeste? Le chemin doit être relatif au fichier manifeste. Vous pouvez me donner l'adresse de votre site web et je peux dire quel est le problème :)
Wojtek Mazurek
1
@ShwetaGulati C'est parce que le navigateur met automatiquement en cache certains fichiers pour accélérer le chargement de la page. C'est un comportement par défaut et ne dépend que du navigateur, vous ne pouvez donc pas le définir de quelque manière que ce soit. En particulier, les fichiers js sont sur la portée du navigateur, car ils sont généralement utilisés sur toutes les pages du site Web, il est donc sage de les mettre en cache. Il n'y a pas d'autre moyen que d'écrire tous les noms de fichiers dans le fichier manifeste pour mettre en cache tous les fichiers. Si vous en trouvez, dites-le-moi, car j'en ai aussi besoin :)
Wojtek Mazurek
1
Le chemin absolu vers vos fichiers n'a pas d'importance. Chemin relatif à partir de l'adresse, car le navigateur envoie la demande de fichiers. F.ex: J'ai le domaine example.com et c'est sur serwer names.com. Mon espace dessus est example.names.com. Je joins donc mon domaine example.com à mon espace serveur example.names.com en tant que redirection. Pour ce faire, je dois définir le dossier comme objectif de cette redirection. Donc, si je veux avoir plusieurs sites sur example.names.com, je crée le dossier "nom1", y redirige et place tous mes fichiers à l'intérieur. Les chemins sont comptés à partir d'ici. Si j'ai nom1 \ scripts \ test.js dans le fichier manifeste, j'écris scripts \ test.js.
Wojtek Mazurek
7

J'ai eu un cas où je prendrais des photos de clients en ligne et aurais besoin de mettre à jour la div si une photo est modifiée. Le navigateur montrait toujours l'ancienne photo. J'ai donc utilisé le hack d'appeler une variable GET aléatoire, qui serait unique à chaque fois. Voilà si cela peut aider quelqu'un

<img src="/photos/userid_73.jpg?random=<?php echo rand() ?>" ...

EDIT Comme indiqué par d'autres, la solution suivante est beaucoup plus efficace car elle ne rechargera les images que lorsqu'elles seront modifiées, identifiant ce changement par la taille du fichier:

<img src="/photos/userid_73.jpg?modified=<? filemtime("/photos/userid_73.jpg")?>"
zeeshan
la source
29
Ce n'est pas élégant du tout, cela ferait que le site rechargerait l'image à chaque fois en perdant beaucoup de temps à télécharger des ressources, une meilleure solution serait d'utiliser la taille du fichier au lieu d'un nombre aléatoire, cela ne revalidera le cache que lorsque le fichier sera réellement changements
Roberto Arosemena
8
Ou un hachage des octets d'image
Taylor Edmiston
1
Tout dépend des exigences de l'utilisateur. Pour un grand nombre de photos, le scénario serait différent de quelques photos. La vérification de la taille du fichier permettrait d'économiser de la bande passante, mais ajouterait également un traitement supplémentaire, ce qui pourrait ralentir le chargement des pages. Dans mon cas, où les images changeaient assez fréquemment et qu'il était essentiel que l'entreprise prenne les photos les plus récentes, c'était une solution parfaite.
zeeshan
Vous pouvez même en faire une valeur statique dans la configuration, ce n'est en aucun cas une approche idéale.
Voyant le
3
<img src = "/ photos / userid_73.jpg? modified = <? = filemtime (" / photos / userid_73.jpg ")?>" serait beaucoup plus utile!
Fusca Software
4

Beaucoup de réponses manquent de raison - la plupart des développeurs sont bien conscients que la désactivation du cache est inefficace. Cependant, il existe de nombreuses circonstances courantes où l'efficacité n'est pas importante et le comportement du cache par défaut est gravement endommagé.

Il s'agit notamment de tests de scripts imbriqués et itératifs (le plus important!) Et de solutions de contournement de logiciels tiers. Aucune des solutions présentées ici n'est adéquate pour répondre à de tels scénarios courants. La plupart des navigateurs Web sont une mise en cache beaucoup trop agressive et ne fournissent aucun moyen raisonnable pour éviter ces problèmes.

John
la source
2

La mise à jour de l'URL vers les œuvres suivantes me convient:

/custom.js?id=1

En ajoutant un numéro unique après ?id=et en l'incrémentant pour de nouvelles modifications, les utilisateurs n'ont pas à appuyer surCTRL + F5 pour actualiser le cache. Alternativement, vous pouvez ajouter une version de hachage ou de chaîne de l'heure actuelle ou Epoch après?id=

Quelque chose comme ?id=1520606295

nPcomp
la source
1

Voici la page MDSN sur la définition de la mise en cache dans ASP.NET.

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(False)
Response.Cache.VaryByParams("Category") = True

If Response.Cache.VaryByParams("Category") Then
   '...
End If
Dave Swersky
la source
1

Je ne sais pas si cela pourrait vraiment vous aider, mais c'est ainsi que la mise en cache devrait fonctionner sur n'importe quel navigateur. Lorsque le navigateur demande un fichier, il doit toujours envoyer une demande au serveur, sauf s'il existe un mode "hors ligne". Le serveur lira certains paramètres comme la date de modification ou les étiquettes.

Le serveur renverra une réponse d'erreur 304 pour NON MODIFIÉ et le navigateur devra utiliser son cache. Si l'etag ne valide pas côté serveur ou si la date de modification est inférieure à la date de modification actuelle, le serveur doit renvoyer le nouveau contenu avec la nouvelle date de modification ou les etags ou les deux.

S'il n'y a pas de données de mise en cache envoyées au navigateur, je suppose que le comportement est indéterminé, le navigateur peut ou non mettre en cache les fichiers qui ne disent pas comment ils sont mis en cache. Si vous définissez des paramètres de mise en cache dans la réponse, il mettra correctement en cache vos fichiers et le serveur peut alors choisir de renvoyer une erreur 304 ou le nouveau contenu.

Voilà comment cela devrait être fait. Utiliser des paramètres aléatoires ou un numéro de version dans les URL est plus un hack qu'autre chose.

http://www.checkupdown.com/status/E304.html http://en.wikipedia.org/wiki/HTTP_ETag http://www.xpertdeveloper.com/2011/03/last-modified-header-vs- expire-header-vs-etag /

Après avoir lu, j'ai vu qu'il y avait aussi une date d'expiration. Si vous avez un problème, il se peut que vous ayez configuré une date d'expiration. En d'autres termes, lorsque le navigateur mettra en cache votre fichier, car il a une date d'expiration, il ne devrait pas avoir à le demander à nouveau avant cette date. En d'autres termes, il ne demandera jamais le fichier au serveur et ne recevra jamais un 304 non modifié. Il utilisera simplement le cache jusqu'à ce que la date d'expiration soit atteinte ou que le cache soit vidé.

C'est donc ma supposition, vous avez une sorte de date d'expiration et vous devez utiliser les derniers etags modifiés ou un mélange de tout cela et vous assurer qu'il n'y a pas de date d'expiration.

Si les gens ont tendance à se rafraîchir beaucoup et que le fichier n'est pas beaucoup modifié, il peut être judicieux de définir une grande date d'expiration.

Mes 2 cents!

Loïc Faure-Lacroix
la source
1

J'ai implémenté cette solution simple qui fonctionne pour moi (pas encore sur l'environnement de production):

function verificarNovaVersio() {
    var sVersio = localStorage['gcf_versio'+ location.pathname] || 'v00.0.0000';
    $.ajax({
        url: "./versio.txt"
        , dataType: 'text'
        , cache: false
        , contentType: false
        , processData: false
        , type: 'post'
     }).done(function(sVersioFitxer) {
        console.log('Versió App: '+ sVersioFitxer +', Versió Caché: '+ sVersio);
        if (sVersio < (sVersioFitxer || 'v00.0.0000')) {
            localStorage['gcf_versio'+ location.pathname] = sVersioFitxer;
            location.reload(true);
        }
    });
}

J'ai un petit fichier situé où se trouvent le html:

"versio.txt":

v00.5.0014

Cette fonction est appelée dans toutes mes pages, donc lors du chargement elle vérifie si la valeur de la version de localStorage est inférieure à la version actuelle et fait un

location.reload(true);

... pour forcer le rechargement depuis le serveur plutôt que depuis le cache.

(évidemment, au lieu de localStorage, vous pouvez utiliser des cookies ou tout autre stockage client persistant)

J'ai opté pour cette solution pour sa simplicité, car seul le maintien d'un seul fichier "versio.txt" forcera le site complet à se recharger.

La méthode queryString est difficile à implémenter et est également mise en cache (si vous passez de la v1.1 à une version précédente se chargera du cache, cela signifie que le cache n'est pas vidé, gardant toutes les versions précédentes dans le cache).

Je suis un petit débutant et j'apprécierais votre vérification et révision professionnelles pour vous assurer que ma méthode est une bonne approche.

J'espère que ça aide.

Seak
la source
0

Il existe une astuce qui peut être utilisée. L'astuce consiste à ajouter un paramètre / chaîne au nom de fichier dans la balise de script et à le modifier lorsque vous modifiez des fichiers.

<script src="myfile.js?version=1.0.0"></script>

Le navigateur interprète la chaîne entière comme le chemin du fichier même si ce qui vient après le "?" sont des paramètres. Donc, ce qui se passe maintenant, c'est que la prochaine fois que vous mettrez à jour votre fichier, changez simplement le numéro dans la balise de script sur votre site Web (exemple <script src="myfile.js?version=1.0.1"></script>) et chaque navigateur d'utilisateurs verra que le fichier a changé et récupérera une nouvelle copie.

Joish
la source
0

Forcer les navigateurs à vider le cache ou à recharger les données correctes?J'ai essayé la plupart des solutions décrites dans stackoverflow, certaines fonctionnent, mais après un certain temps, il cache finalement et affiche le script ou fichier chargé précédent. Existe-t-il une autre façon de vider le cache (css, js, etc.) et de fonctionner réellement sur tous les navigateurs?

J'ai trouvé jusqu'à présent que des ressources spécifiques peuvent être rechargées individuellement si vous modifiez la date et l'heure de vos fichiers sur le serveur. "Vider le cache" n'est pas aussi simple qu'il devrait l'être. Au lieu de vider le cache sur mes navigateurs, j'ai réalisé que "toucher" les fichiers du serveur mis en cache changerait en fait la date et l'heure du fichier source mis en cache sur le serveur (testé sur Edge, Chrome et Firefox) et la plupart des navigateurs téléchargeront automatiquement le plus nouvelle copie actuelle de ce qui est sur votre serveur (code, graphiques et multimédia également). Je vous suggère de copier les scripts les plus récents sur le serveur et de faire la chose "tactile" avant que votre programme ne s'exécute, donc il changera la date de tous vos fichiers problématiques en une date et une heure les plus récentes, puis il télécharge une nouvelle copie à votre navigateur:

<?php
   touch('/www/sample/file1.css');
   touch('/www/sample/file2.js');
?>

alors ... le reste de votre programme ...

Il m'a fallu un certain temps pour résoudre ce problème (car de nombreux navigateurs agissent différemment des différentes commandes, mais ils vérifient tous l'heure des fichiers et se comparent à votre copie téléchargée dans votre navigateur, si une date et une heure différentes feront le rafraîchissement), si vous ne peut pas aller dans le bon sens, il y a toujours une autre solution utilisable et meilleure. Cordialement et camping heureux. Au fait, touchez (); ou des alternatives fonctionnent dans de nombreux langages de programmation inclus en javascript bash sh php et vous pouvez les inclure ou les appeler en html.

Luis H Cabrejo
la source
1
si le fichier est modifié, l'horodatage est déjà modifié de toute façon, il n'y a donc aucun avantage à le forcer à nouveau.
Fusca Software
La commande tactile ne change pas du tout le fichier. Il change l'attribut de date et d'heure, le convertissant en une version plus récente trompant le navigateur pour le télécharger en tant que nouvelle copie.
Luis H Cabrejo
-1

Voulez-vous vider le cache ou simplement vous assurer que votre page actuelle (modifiée?) N'est pas mise en cache?

Si ce dernier, il devrait être aussi simple que

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
Tim Crone
la source
J'ai lu récemment sur cette approche dans une publication Chrome, et je n'ai trouvé des résultats cohérents que sur une poignée de serveurs en direct, d'hôte local et de partage de fichiers Windows ... avec Firefox 3.6.
danjah