J'ai remarqué que certains navigateurs (en particulier Firefox et Opera) sont très zélés dans l'utilisation de copies en cache des fichiers .css et .js , même entre les sessions du navigateur. Cela entraîne un problème lorsque vous mettez à jour l'un de ces fichiers, mais le navigateur de l'utilisateur continue d'utiliser la copie mise en cache.
La question est: quelle est la manière la plus élégante de forcer le navigateur de l'utilisateur à recharger le fichier lorsqu'il a changé?
Idéalement, la solution ne forcerait pas le navigateur à recharger le fichier à chaque visite de la page. Je posterai ma propre solution comme réponse, mais je suis curieux de savoir si quelqu'un a une meilleure solution et je laisserai vos votes décider.
Mise à jour :
Après avoir autorisé la discussion ici pendant un certain temps, j'ai trouvé la suggestion de John Millikin et da5id utile. Il s'avère qu'il y a un terme pour cela: la version automatique .
J'ai posté une nouvelle réponse ci-dessous qui est une combinaison de ma solution d'origine et de la suggestion de John.
Une autre idée suggérée par SCdF serait d'ajouter une fausse chaîne de requête au fichier. (Du code Python pour utiliser automatiquement l'horodatage comme chaîne de requête bidon a été soumis par pi .). Cependant, il y a une discussion pour savoir si le navigateur mettra en cache ou non un fichier avec une chaîne de requête. (N'oubliez pas que nous souhaitons que le navigateur mette le fichier en cache et l'utilise lors de vos prochaines visites. Nous souhaitons uniquement qu'il récupère le fichier lorsqu'il a changé.)
Puisqu'il n'est pas clair ce qui se passe avec une fausse chaîne de requête, je n'accepte pas cette réponse.
ExpiresActive On ExpiresDefault "modification"
.iframe.contentWindow.location.reload(true)
. Voir la méthode (4) de stackoverflow.com/a/22429796/999120 - il s'agit d'images, mais la même chose s'applique.Réponses:
Mise à jour: réécriture pour incorporer les suggestions de John Millikin et da5id . Cette solution est écrite en PHP, mais devrait être facilement adaptée à d'autres langages.
Mise à jour 2: Incorporation des commentaires de Nick Johnson selon lesquels l'
.htaccess
expression régulière originale peut causer des problèmes avec des fichiers commejson-1.3.js
. La solution consiste à réécrire uniquement s'il y a exactement 10 chiffres à la fin. (Parce que 10 chiffres couvrent tous les horodatages du 9/9/2001 au 11/20/2286.)Tout d'abord, nous utilisons la règle de réécriture suivante dans .htaccess:
Maintenant, nous écrivons la fonction PHP suivante:
Maintenant, où que vous incluiez votre CSS, changez-le à partir de ceci:
Pour ça:
De cette façon, vous n'aurez plus jamais à modifier la balise de lien et l'utilisateur verra toujours la dernière CSS. Le navigateur pourra mettre en cache le fichier CSS, mais lorsque vous apporterez des modifications à votre CSS, le navigateur le verra comme une nouvelle URL, donc il n'utilisera pas la copie mise en cache.
Cela peut également fonctionner avec des images, des favicons et JavaScript. Fondamentalement, tout ce qui n'est pas généré dynamiquement.
la source
file_exists
contrôle est-il vraiment nécessaire?filemtime
retournera false en cas d'échec, alors pourquoi ne pas simplement attribuer la valeur filemtime à une variable et vérifier si elle est fausse avant de renommer le fichier? Cela réduirait une opération de fichier inutile qui s'additionnerait vraiment.Technique simple côté client
En général, la mise en cache est bonne. Il existe donc quelques techniques, selon que vous résolvez le problème par vous-même lorsque vous développez un site Web ou que vous essayez de contrôler le cache dans un environnement de production.
Les visiteurs généraux de votre site Web n'auront pas la même expérience que vous avez lorsque vous développez le site. Étant donné que le visiteur moyen vient sur le site moins fréquemment (peut-être seulement quelques fois par mois, sauf si vous êtes un réseau Google ou hi5), il est donc moins susceptible d'avoir vos fichiers en cache, et cela peut suffire. Si vous souhaitez forcer une nouvelle version dans le navigateur, vous pouvez toujours ajouter une chaîne de requête à la demande et augmenter le numéro de version lorsque vous apportez des modifications majeures:
Cela garantira que tout le monde obtient le nouveau fichier. Cela fonctionne car le navigateur regarde l'URL du fichier pour déterminer s'il a une copie dans le cache. Si votre serveur n'est pas configuré pour faire quoi que ce soit avec la chaîne de requête, il sera ignoré, mais le nom ressemblera à un nouveau fichier pour le navigateur.
En revanche, si vous développez un site Web, vous ne voulez pas changer le numéro de version à chaque fois que vous enregistrez une modification dans votre version de développement. Ce serait fastidieux.
Ainsi, pendant que vous développez votre site, une bonne astuce serait de générer automatiquement un paramètre de chaîne de requête:
L'ajout d'une chaîne de requête à la demande est un bon moyen de versionner une ressource, mais pour un site Web simple, cela peut être inutile. Et rappelez-vous, la mise en cache est une bonne chose.
Il convient également de noter que le navigateur n'est pas nécessairement avare de conserver les fichiers en cache. Les navigateurs ont des politiques pour ce genre de choses, et ils respectent généralement les règles définies dans la spécification HTTP. Lorsqu'un navigateur fait une demande à un serveur, une partie de la réponse est un en-tête EXPIRES. Une date qui indique au navigateur combien de temps il doit être conservé dans le cache. La prochaine fois que le navigateur rencontre une demande pour le même fichier, il voit qu'il a une copie en cache et regarde la date EXPIRE pour décider s'il doit être utilisé.
Croyez-le ou non, c'est en fait votre serveur qui rend le cache du navigateur si persistant. Vous pouvez ajuster les paramètres de votre serveur et modifier les en-têtes EXPIRES, mais la petite technique que j'ai écrite ci-dessus est probablement un moyen beaucoup plus simple de vous y prendre. Étant donné que la mise en cache est bonne, vous souhaitez généralement définir cette date très loin dans le futur (un "en-tête expirant dans un futur éloigné") et utiliser la technique décrite ci-dessus pour forcer un changement.
Si vous êtes intéressé par plus d'informations sur HTTP ou comment ces demandes sont faites, un bon livre est "High Performance Web Sites" de Steve Souders. C'est une très bonne introduction au sujet.
la source
<link href='myCss.css?dev=14141'...>
Mod_pagespeed de Google plugin pour apache effectuera la version automatique pour vous. C'est vraiment lisse.
Il analyse le HTML à sa sortie du serveur Web (fonctionne avec PHP, rails, python, HTML statique - n'importe quoi) et réécrit les liens vers CSS, JS, fichiers image afin qu'ils incluent un code d'identification. Il sert les fichiers aux URL modifiées avec un contrôle de cache très long sur eux. Lorsque les fichiers changent, il modifie automatiquement les URL de sorte que le navigateur doit les récupérer de nouveau. Cela fonctionne simplement, sans aucune modification de votre code. Cela réduira également votre code à la sortie.
la source
Au lieu de changer la version manuellement, je vous recommande d'utiliser un hachage MD5 du fichier CSS réel.
Donc, votre URL serait quelque chose comme
Vous pouvez toujours utiliser la règle de réécriture pour supprimer le hachage, mais l'avantage est que vous pouvez maintenant définir votre stratégie de cache sur "cache pour toujours", car si l'URL est la même, cela signifie que le fichier est inchangé.
Vous pouvez ensuite écrire un script shell simple qui calculerait le hachage du fichier et mettrait à jour votre balise (vous voudriez probablement le déplacer vers un fichier séparé pour l'inclusion).
Exécutez simplement ce script chaque fois que CSS change et vous êtes bon. Le navigateur rechargera UNIQUEMENT vos fichiers lorsqu'ils seront modifiés. Si vous effectuez une modification puis l'annulez, il n'y a aucune difficulté à déterminer la version à laquelle vous devez revenir pour que vos visiteurs ne téléchargent pas à nouveau.
la source
Je ne sais pas pourquoi vous prenez tant de peine à mettre en œuvre cette solution.
Tout ce que vous devez faire si obtenir l'horodatage modifié du fichier et l'ajouter en tant que chaîne de requête au fichier
En PHP, je le ferais comme:
filemtime est une fonction PHP qui renvoie l'horodatage modifié du fichier.
la source
mycss.css?1234567890
.<link rel="stylesheet" href="mycss.css?<?php echo filemtime('mycss.css') ?>"/>
, juste au cas où certains des arguments sur ce fil concernant la mise en cache des URL avec des variables GET (dans le format suggéré) sont corrects?ver=
alors qui sait!Vous pouvez simplement mettre
?foo=1234
à la fin de votre import css / js, en changeant 1234 pour être ce que vous voulez. Jetez un œil à la source SO html pour un exemple.L'idée étant que le? les paramètres sont de toute façon ignorés / ignorés sur la demande et vous pouvez modifier ce nombre lorsque vous déployez une nouvelle version.
Remarque: Il existe un argument concernant la façon exacte dont cela affecte la mise en cache. Je pense que l'essentiel est que les requêtes GET, avec ou sans paramètres, doivent être cachable, donc la solution ci-dessus devrait fonctionner.
Cependant, c'est au serveur Web de décider s'il veut adhérer à cette partie de la spécification et au navigateur que l'utilisateur utilise, car il peut tout de même aller de l'avant et demander une nouvelle version de toute façon.
la source
J'ai entendu cela appelé "versioning automatique". La méthode la plus courante consiste à inclure le mtime du fichier statique quelque part dans l'URL et à le supprimer à l'aide de gestionnaires de réécriture ou de confs d'URL:
Voir également:
la source
La trentaine de réponses existantes sont d'excellents conseils pour un site Web vers 2008. Cependant, en ce qui concerne une application de page unique (SPA) moderne, il est peut-être temps de repenser certaines hypothèses fondamentales… en particulier l'idée qu'il est souhaitable que le serveur Web ne serve que la version unique et la plus récente d'un fichier.
Imaginez que vous êtes un utilisateur dont la version M d'un SPA est chargée dans votre navigateur:
/some.template
/some.template
- voulez-vous qu'il renvoie la version M ou N du modèle?Si le format a
/some.template
changé entre les versions M et N (ou si le fichier a été renommé ou autre), vous ne voulez probablement pas que la version N du modèle soit envoyée au navigateur qui exécute l'ancienne version M de l'analyseur . †Les applications Web rencontrent ce problème lorsque deux conditions sont remplies:
Une fois que votre application doit servir plusieurs versions en parallèle, résoudre la mise en cache et le «rechargement» devient trivial:
/v<release_tag_1>/…files…
,/v<release_tag_2>/…files…
<script>
et<link>
balises, etc. pour pointer vers ce fichier dans l' un des dirs versionnésCette dernière étape semble délicate, car elle pourrait nécessiter d'appeler un générateur d'URL pour chaque URL de votre code côté serveur ou côté client. Ou vous pouvez simplement utiliser intelligemment la
<base>
balise et modifier la version actuelle en un seul endroit.† Une façon de contourner ce problème consiste à forcer le navigateur à tout recharger lorsqu'une nouvelle version est publiée. Mais pour permettre à toutes les opérations en cours de se terminer, il peut toujours être plus facile de prendre en charge au moins deux versions en parallèle: v-current et v-previous.
la source
base
tag! Quant à la prise en charge de l'ancien code: ce n'est pas toujours une possibilité, ce n'est pas toujours une bonne idée. Les nouvelles versions de code peuvent prendre en charge les modifications de rupture apportées à d'autres éléments d'une application ou impliquer des correctifs d'urgence, des correctifs de vulnérabilité, etc. Je n'ai pas encore implémenté cette stratégie moi-même, mais j'ai toujours pensé que l'architecture globale devrait permettre aux déploiements de marquer une ancienne version en tant queobsolete
et de forcer un rechargement la prochaine fois qu'un appel asynchrone est effectué (ou tout simplement de-authentifier de force toutes les sessions via WebSockets ).N'utilisez pas foo.css? Version = 1! Les navigateurs ne sont pas censés mettre en cache les URL avec des variables GET. Selon http://www.thinkvitamin.com/features/webapps/serving-javascript-fast , bien qu'IE et Firefox l'ignorent, Opera et Safari ne le font pas! Utilisez plutôt foo.v1234.css et utilisez des règles de réécriture pour supprimer le numéro de version.
la source
Dans Laravel (PHP), nous pouvons le faire de manière claire et élégante (en utilisant l'horodatage de modification de fichier):
Et similaire pour CSS
Exemple de sortie html (
filemtime
heure de retour sous forme d' horodatage Unix )la source
La RewriteRule a besoin d'une petite mise à jour pour les fichiers js ou css qui contiennent un versionnage de notation par points à la fin. Par exemple json-1.3.js.
J'ai ajouté une classe de négation de points [^.] À l'expression régulière afin .number. est ignoré.
la source
^(.*)\.[\d]{10}\.(css|js)$ $1.$2
[^.]
ici. De plus, il n'y a aucun avantage à écrire à l'\d
intérieur d'une classe de caractères -\d+
fera la même chose. Tel que publié, votre modèle correspondra à n'importe quel nombre de caractères (avec avidité), puis un point littéral, puis un non-point, puis un ou plusieurs chiffres, puis un point, puiscss
oujs
, puis la fin du nom de fichier. Aucune correspondance pour votre échantillon d'entrée: regex101.com/r/RPGC62/1Pour ASP.NET 4.5 et supérieur, vous pouvez utiliser le regroupement de scripts .
Le regroupement présente d'autres avantages, notamment des performances accrues lors des premiers chargements de pages avec minification.
la source
Voici une solution JavaScript pure
Ce qui précède recherchera la dernière fois que l'utilisateur a visité votre site. Si la dernière visite a eu lieu avant la publication du nouveau code, il utilise
location.reload(true)
pour forcer l'actualisation de la page à partir du serveur.J'ai généralement ceci comme premier script dans le
<head>
donc il est évalué avant tout autre chargement de contenu. Si un rechargement doit avoir lieu, il est à peine perceptible par l'utilisateur.J'utilise le stockage local pour stocker l'horodatage de la dernière visite sur le navigateur, mais vous pouvez ajouter des cookies au mix si vous souhaitez prendre en charge les anciennes versions d'IE.
la source
Poste intéressant. Après avoir lu toutes les réponses ici combinées avec le fait que je n'ai jamais eu de problème avec les chaînes de requête "fausses" (dont je ne sais pas pourquoi tout le monde est si réticent à l'utiliser), je suppose que la solution (qui supprime le besoin de règles de réécriture apache comme dans la réponse acceptée) consiste à calculer un court HASH du contenu du fichier CSS (au lieu du fichier datetime) en tant que chaîne de requête bidon.
Cela se traduirait par ce qui suit:
Bien sûr, les solutions datetime font également le travail dans le cas de la modification d'un fichier CSS mais je pense qu'il s'agit du contenu du fichier css et non du datetime du fichier, alors pourquoi les mélanger?
la source
Pour mon développement, je trouve que le chrome a une excellente solution.
https://developer.chrome.com/devtools/docs/tips-and-tricks#hard-reload
Avec les outils de développement ouverts, cliquez simplement longuement sur le bouton d'actualisation et relâchez une fois que vous survolez "Cache vide et rechargement dur".
Ceci est mon meilleur ami, et est un moyen super léger pour obtenir ce que vous voulez!
la source
Merci à Kip pour sa solution parfaite!
Je l'ai étendu pour l'utiliser comme un Zend_view_Helper. Parce que mon client a exécuté sa page sur un hôte virtuel, je l'ai également étendu pour cela.
J'espère que ça aide quelqu'un d'autre aussi.
Bravo et merci.
la source
N'ont pas trouvé l'approche DOM côté client créant dynamiquement l'élément de nœud de script (ou css):
la source
Google Chrome a dur Recharger ainsi que Vider le cache et dur Recharger option.You pouvez cliquer sur le bouton de rechargement (En mode Inspect) pour sélectionner un.
la source
ant menu
>More Tools
>Developer Tools
, aliasright click
>Inspect Element
. Il y a aussi un paramètre enfoui quelque part dans les outils de développement (j'oublie l'emplacement) pour recharger à chaque rechargement.Vous pouvez forcer une "mise en cache à l'échelle de la session" si vous ajoutez l'ID de session en tant que paramètre complet du fichier js / css:
Si vous souhaitez une mise en cache à l'échelle de la version, vous pouvez ajouter du code pour imprimer la date du fichier ou similaire. Si vous utilisez Java, vous pouvez utiliser une balise personnalisée pour générer le lien de manière élégante.
la source
Supposons qu'un fichier soit disponible sur:
vous pouvez soit ajouter un paramètre de requête avec des informations de version sur l'URI, par exemple:
ou vous pouvez ajouter des informations de version, par exemple:
À mon humble avis, la deuxième méthode est meilleure pour les fichiers CSS, car ils peuvent faire référence à des images à l'aide d'URL relatives, ce qui signifie que si vous spécifiez une
background-image
telle chose :son URL sera effectivement:
Cela signifie que si vous mettez à jour le numéro de version utilisé, le serveur traitera cela comme une nouvelle ressource et n'utilisera pas de version mise en cache. Si vous basez votre numéro de version sur Subversion / CVS / etc. révision cela signifie que les modifications des images référencées dans les fichiers CSS seront remarquées. Ce n'est pas garanti avec le premier schéma, à savoir l'URL
images/happy.gif
relative à/styles/screen.css?v=1235
is/styles/images/happy.gif
ne contient aucune information de version.J'ai implémenté une solution de mise en cache en utilisant cette technique avec des servlets Java et je gère simplement les demandes
/v/*
avec un servlet qui délègue à la ressource sous-jacente (c'est-à-dire/styles/screen.css
). En mode de développement , je mis en cache les en- têtes qui indiquent au client de toujours vérifier la fraîcheur de la ressource avec le serveur (ce qui se traduit généralement par un 304 si vous déléguez à Tomcat deDefaultServlet
et.css
,.js
, etc. fichier n'a pas changé) en mode déploiement J'ai mis des en-têtes qui disent "cache pour toujours".la source
<?php header( 'Location: folder1/login.phtml' ); ?>
.Vous pouvez simplement ajouter un nombre aléatoire avec l'URL CSS / JS comme
la source
Pour ASP.NET, je suppose que la prochaine solution avec des options avancées (mode debug / release, versions):
Fichiers Js ou Css inclus de cette manière:
Global.JsPostfix et Global.CssPostfix est calculé de la manière suivante dans Global.asax:
la source
J'ai récemment résolu cela en utilisant Python. Voici le code (devrait être facile à adopter dans d'autres langues):
Ce code ajoute fondamentalement l'horodatage des fichiers en tant que paramètre de requête à l'URL. L'appel de la fonction suivante
aura pour résultat
L'avantage est bien sûr que vous n'aurez plus jamais à changer votre html, toucher le fichier CSS déclenchera automatiquement une invalidation du cache. Fonctionne très bien et les frais généraux ne sont pas perceptibles.
la source
Si vous utilisez git + PHP, vous pouvez recharger le script depuis le cache chaque fois qu'il y a un changement dans le dépôt git, en utilisant le code suivant:
la source
Si vous êtes un développeur qui cherche à éviter la mise en cache, l'onglet réseau Chrome a désactivé l'option de cache. Sinon, vous pouvez le faire sans infrastructure de rendu de serveur à l'aide de deux balises de script.
la source
Cette question est super ancienne et apparaît en premier lieu lorsque quelqu'un google ce problème. Ce n'est pas une réponse à la question de la façon dont op le souhaite, mais plutôt une réponse aux développeurs avec ce problème lors du développement et des tests. Et je ne peux pas poster une nouvelle question sur ce sujet car sera marqué comme doublon.
Comme beaucoup d'autres, je voulais juste supprimer brièvement la mise en cache.
"keep caching consistent with the file"
.. sa manière trop de tracas ..D'une manière générale, cela ne me dérange pas de charger plus - même de charger à nouveau des fichiers qui n'ont pas changé - sur la plupart des projets - est pratiquement hors de propos. Lors du développement d'une application - nous chargeons principalement à partir du disque, sur
localhost:port
- donc ceincrease in network traffic
problème n'est pas un problème de rupture d'accord .La plupart des petits projets ne font que jouer - ils ne finissent jamais en production. donc pour eux vous n'avez besoin de rien de plus ..
En tant que tel, si vous utilisez Chrome Dev Tools , vous pouvez suivre cette approche de désactivation de la mise en cache comme dans l'image ci-dessous:
Et si vous avez des problèmes de mise en cache de Firefox :
Pour ce faire uniquement en développement, vous avez également besoin d'un mécanisme pour forcer le rechargement pour la production, car vos utilisateurs utiliseront les anciens modules invalides du cache si vous mettez à jour votre application fréquemment et que vous ne fournissez pas de mécanisme de synchronisation de cache dédié comme ceux décrits dans les réponses au dessus de.
Oui, ces informations figurent déjà dans les réponses précédentes, mais j'avais encore besoin de faire une recherche Google pour les trouver.
J'espère que cette réponse est très claire et que vous n'en avez plus besoin.
la source
Il semble que toutes les réponses suggèrent une sorte de versioning dans le schéma de nommage, qui a ses inconvénients.
Les navigateurs doivent bien savoir quoi mettre en cache et quoi ne pas mettre en cache en lisant la réponse des serveurs Web, en particulier les en-têtes http - pendant combien de temps cette ressource est-elle valide? cette ressource a-t-elle été mise à jour depuis ma dernière récupération? etc.
Si les choses sont configurées «correctement», la simple mise à jour des fichiers de votre application devrait (à un moment donné) rafraîchir les caches des navigateurs. Vous pouvez par exemple configurer votre serveur Web pour dire au navigateur de ne jamais mettre en cache les fichiers (ce qui est une mauvaise idée).
Une explication plus approfondie de la façon dont cela fonctionne est ici https://www.mnot.net/cache_docs/#WORK
la source
Ajoutez simplement ce code, où vous voulez effectuer un rechargement dur (forcer le navigateur à recharger les fichiers CSS / JS mis en cache) Faites-le à l'intérieur du .load pour qu'il ne se rafraîchisse pas comme une boucle
la source
Utilisez simplement le code côté serveur pour ajouter la date du fichier ... de cette façon, il sera mis en cache et rechargé uniquement lorsque le fichier change
Dans ASP.NET
Cela peut être simplifié pour:
En ajoutant une méthode d'extension à votre projet pour étendre la page:
la source
Je suggère de mettre en œuvre le processus suivant:
versionnez vos fichiers css / js chaque fois que vous déployez, quelque chose comme: screen.1233.css (le numéro peut être votre révision SVN si vous utilisez un système de versioning)
les minimiser pour optimiser les temps de chargement
la source