Arrêter le navigateur pour faire des requêtes HTTP pour des images qui devraient rester cachées-mod expire
après avoir lu de nombreux articles et quelques questions ici, j'ai finalement réussi à activer L'Apache mod_expires
pour dire au navigateur qu'il doit mettre en cache des images pour 1 an .
<filesMatch ".(ico|gif|jpg|png)$">
ExpiresActive On
ExpiresDefault "access plus 1 year"
Header append Cache-Control "public"
</filesMatch>
et heureusement les réponses du serveur semblent être correctes:
HTTP/1.1 200 OK
Date: Fri, 06 Apr 2012 19:25:30 GMT
Server: Apache
Last-Modified: Tue, 26 Jul 2011 18:50:14 GMT
Accept-Ranges: bytes
Content-Length: 24884
Cache-Control: max-age=31536000, public
Expires: Sat, 06 Apr 2013 19:25:30 GMT
Connection: close
Content-Type: image/jpeg
Eh bien, je pensais que cela arrêterait le navigateur pour télécharger et même demander au serveur sur les images pour 1 an. Mais c'est partiellement vrai: cause si vous fermez et rouvrez le navigateur, le navigateur ne télécharge plus les images à partir du serveur, mais le navigateur demande toujours au serveur une requête HTTP pour chaque image .
comment forcer le navigateur à arrêter de faire des requêtes HTTP pour chaque image? Même si ces requêtes HTTP ne sont pas suivies par le téléchargement d'une image, il s'agit quand même de requêtes adressées au serveur qui diminuent inutilement la latence. et ralentissez le rendu des pages!
j'ai déjà dit au navigateur qu'il doit garder les images en cache pour 1 an! Pourquoi le navigateur interroge-t-il toujours le serveur pour chaque image (même s'il ne télécharge pas l'image)?!
en regardant les graphiques réseau dans FireBug (menu FireBug > Net > Images) je peux voir différents comportements de mise en cache (j'ai évidemment commencé avec le navigateur cache complètement vide, j'ai forcé un cache supprimer sur le navigateur en utilisant "Effacer Toute L'Histoire"):
-
lorsque la page est chargée pour la première fois toutes les images sont téléchargées (et la même chose se produit si je force une page recharger en cliquant sur le bouton page de rechargement du navigateur). c'est logique!
-
quand je navigue sur le site et revenir à la même page les images ne sont pas téléchargées du tout et le le navigateur ne demande même pas au serveur pour aucune des images. cela a du sens, (et j'aimerais voir ce comportement aussi quand le navigateur est fermé)!
-
lorsque je ferme le navigateur et que je l'ouvre à nouveau sur la même page, le navigateur idiot fait quand même une demande HTTP au serveur une fois par image: il ne downalod l'image, mais il fait encore une demande HTTP, c'est comme le le navigateur interroge le serveur sur l'image (le serveur répond avec 200 OK). C'est celui qui m'irrite!
je joins également les graphiques ci-dessous si vous êtes intéressé:
EDIT: vient de tester maintenant aussi avec FireFox 11.0 juste pour s'assurer que ce n'était pas un problème de mon FireFox 3.6 d'être trop vieux. La même chose se passe!!! j'ai également testé Google site et Stackoverlow site , ils font à la fois envoyer le Cache-Control: max-age=...
mais le navigateur fait toujours une demande HTTP au serveur pour chaque image Une fois que le navigateur est fermé et ouvert à nouveau sur la même page , après la réponse du serveur le navigateur ne télécharge pas l'image (comme je l'ai expliqué ci-dessus), mais il fait toujours la fichue demande qui augmente le temps de voir la page.
EDIT2: et supprimer l'en-tête Last-Modified
comme suggéré ici , ne résout pas le problème, il ne fait aucune différence.
10 réponses
vous utilisiez le mauvais outil pour analyser les requêtes.
je recommande L'addon très utile de Firefox en-têtes HTTP Live pour que vous puissiez voir ce qui se passe vraiment sur le réseau.
et juste pour être sûr, vous pouvez ssh / putty votre serveur et faire quelque chose comme
tail -f /var/log/apache2/access.log
le comportement que vous voyez est le comportement prévu (voir RFC7234 pour plus de détails), comportement spécifié:
tous les navigateurs modernes enverront des requêtes HTTP au serveur pour chaque élément de page affiché, quel que soit l'état du cache. Il s'agissait d'une décision de conception prise à la demande des services web (en particulier les réseaux de publicité) pour s'assurer que les serveurs HTTP étaient en mesure de maintenir des enregistrements de chaque affichage de chaque élément.
si les navigateurs ne font pas ces requêtes, le serveur ne sera jamais avisé qu'une image a été affichée à l'utilisateur. Pour les réseaux de publicité, ce serait catastrophique. Au début, les réseaux publicitaires ont "piraté" leur façon de contourner ce problème en diffusant la même image publicitaire en utilisant des noms générés au hasard (ex: "coke_ad_1_98719283719283.gif'). Toutefois, pour les fournisseurs de services Internet, cette pratique a entraîné une augmentation considérable des transferts de données, car chacun de leurs utilisateurs téléchargeait à nouveau ces annonces identiques. images, en contournant tous les serveurs de cache / proxy que leur fournisseur d'accès internet exploitait.
donc une trêve a été atteinte: les navigateurs enverraient toujours des requêtes HTTP, même pour les éléments non-expirés en cache. Les serveurs répondraient avec les codes de statut HTTP 304 ("non modifié"). Cela permet aux serveurs d'enregistrer le fait que l'image est affichée au client. En conséquence, les réseaux publicitaires en général ont cessé d'utiliser des noms d'image aléatoires pour contourner les serveurs de cache réseau.
cela a donné aux réseaux publicitaires ce qu'ils voulaient - un enregistrement de chaque image affichée - et cela a donné aux fournisseurs de services Internet ce qu'ils voulaient - des images pouvant être mises en cache et du contenu statique.
C'est pourquoi il n'y a pas grand chose que vous puissiez faire pour empêcher les navigateurs D'envoyer des requêtes HTTP pour des éléments de page en cache.
mais si vous regardez d'autres solutions client-side disponibles qui sont venus avec html5, il y a une possibilité d'empêcher le chargement de ressources
- Cache Manifest (malgré ses gotchas)
- IndexedDB (nice fonctionnalités asynchrones, permet le stockage blob)
- Stockage Local (pas async)
Il y a une différence entre "recharger" et "rafraîchissant". Le simple fait de naviguer sur une page avec les boutons "back" et "forward" ne déclenche généralement pas de nouvelles requêtes HTTP, mais en appuyant spécifiquement sur F5 pour "rafraîchir" la page, le navigateur va vérifier deux fois son cache. Cela dépend du navigateur mais semble être la norme pour FF et Chrome (c.-à-d. les navigateurs qui ont la capacité de regarder facilement leur trafic réseau.) En appuyant sur F6, enter devrait concentrer la barre D'adresse URL et ensuite "aller" à elle, qui devrait recharger la page mais ne pas revérifier les actifs sur la page.
Update : clarification du comportement de navigation arrière et avant. Il s'appelle " Back Forward Cache "ou BFCache dans les navigateurs. Lorsque vous naviguez avec les boutons suivant/précédent, l'intention est de vous montrer exactement que la page était quand vous l'avez vu dans votre propre calendrier. Aucune requête de serveur n'est faite lors de l'utilisation de back and forward, même si un en-tête de cache de serveur dit qu'un élément particulier expiré.
si vous voyez (200 OK BFCache) dans votre panneau réseau de développeur, alors le serveur n'a jamais été touché - même pour demander si-modifié-depuis.
http://www.softwareishard.com/blog/firebug/firebug-tip-what-the-heck-is-bfcache /
si je force un rafraîchissement en utilisant F5 ou F5 + Ctrl, une requête est envoyée. Cependant, si je ferme le navigateur et que j'entre à nouveau l'url, alors aucun reqeust n'est envoyé. La façon dont j'ai testé si une requête est envoyée ou non était en utilisant des points de rupture sur la requête begin sur le serveur, même si une requête n'est pas envoyée, elle apparaît toujours dans Firebug comme ayant fait une attente de 7 ms, donc attention.
ce que vous décrivez ici ne reflète pas mon expérience. Si le contenu est servi avec une directive no-store ou que vous faites une mise à jour explicite, alors oui, je m'attendrais à ce qu'il retourne au serveur d'origine sinon il devrait être mis en cache à travers le redémarrage du navigateur (en supposant qu'il soit autorisé à, et peut écrire un fichier de cache).
regarder vos chutes d'eau dans un peu plus de détails (ce qui est délicat, car ils sont un peu petits et flous) le navigateur semble faire exactement ce qu'il est - ce que - it a des entrées pour les images - mais celles-ci ne font que charger à partir du cache local pas à partir du serveur d'origine-Vérifiez l'en-tête "Date" dans la réponse (Pourquoi pensez-vous que cela prend des millisecondes au lieu de secondes?). C'est pourquoi ils sont colorés différemment.
après avoir passé beaucoup de temps à chercher une réponse raisonnable, j'ai trouvé le lien ci-dessous le plus utile et il répond à la question posée ici.
si c'est une question de vie ou de mort (si vous voulez optimiser le chargement de la page de cette façon ou si vous voulez réduire la charge sur le serveur autant que possible, peu importe quoi), alors il y a une solution.
utilisez HTML5 local storage pour mettre en cache des images après qu'elles aient été demandées pour la première fois.
-
[+] vous pouvez empêcher le navigateur D'envoyer des requêtes HTTP, qui en 99% retournerait 304 (non modifié), peu importe les efforts de l'utilisateur (F5, ctrl+F5, simplement revisiter la page, etc.)
-
[-] vous devez mettre quelques efforts supplémentaires dans le soutien de javascript pour ceci.
-
[-] les Images sont stockées dans base64 (nous ne pouvons pas stocker de données binaires), c'est pourquoi elles sont décodées à chaque fois du côté du client. Qui est habituellement assez rapide et pas grand chose, mais c'est encore une utilisation supplémentaire du cpu côté client et devrait être gardée à l'esprit.
-
[-] le stockage Local est limité. Vous pouvez viser à utiliser ~5mb de données par domaine (Note: base64 ajoute ~30% à la taille originale de l'image).
-
[?] , Soutenu par "1519230920 de la" majorité des navigateurs. http://caniuse.com/#search=localstorage
ce que vous voyez dans Chrome n'est pas un enregistrement des requêtes HTTP réelles - c'est un enregistrement des requêtes asset. Chrome fait cela pour vous montrer qu'un actif est réellement demandé par la page. Toutefois, ce point de vue n'indique pas vraiment si la demande est faite. Si un actif est mis en cache, Chrome ne créera jamais la requête HTTP sous-jacente.
vous pouvez également le confirmer en survolant les segments violets de la ligne de temps. Mis en cache ressources aura un (from cache)
dans le tooltip.
pour voir les requêtes HTTP actuelles, vous devez regarder à un niveau inférieur. Dans certains navigateurs, cela peut être fait avec un plugin (comme les en-têtes HTTP Live).
en réalité cependant, pour vérifier que les requêtes ne sont pas réellement faites, vous devez vérifier les logs de votre serveur ou utiliser un proxy de débogage comme Charles ou Fiddler. Cela fonctionnera au niveau HTTP pour s'assurer que les requêtes ne se produisent pas réellement.
validation du Cache et réponse 304
il existe un certain nombre de situations dans lesquelles Internet Explorer doit vérifier si une entrée mise en cache est valide:
-
l'entrée en cache n'a pas de date d'expiration et le contenu est accédé pour la première fois dans une session de navigateur
-
l'Entrée mise en cache a une date d'expiration mais elle a expiré
- l'Utilisateur a demandé une mise à jour de page en cliquant sur le bouton rafraîchir ou en appuyant sur F5
si l'Entrée mise en cache a une date de dernière modification, IE l'envoie dans l'en-tête If-Modified-Since d'un message de requête GET:
GET /images/logo.gif HTTP/1.1
Accept: */*
Referer: http://www.google.com/
Accept-Encoding: gzip, deflate
If-Modified-Since: Thu, 23 Sep 2004 17:42:04 GMT
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;)
Host: www.google.com
le serveur vérifie l'en-tête If-Modified-Since et répond en conséquence. Si le contenu n'a pas été modifié depuis la date/heure spécifiée, il répond avec un code d'état de 304 et un message de réponse qui contient uniquement les en-têtes:
HTTP/1.1 304 Not Modified
Content-Type: text/html
Server: GWS/2.1
Content-Length: 0
Date: Thu, 04 Oct 2004 12:00:00 GMT
la réponse peut être téléchargée rapidement car elle ne contient pas de contenu et amène IE à lire les données dont elle a besoin depuis le cache. En effet, il s'agit d'une redirection vers le cache du navigateur local.
si l'objet demandé a effectivement changé depuis la date / heure dans L'en-tête If-Modified-Since, les réponses du serveur avec un code d'état de 200 et fournit la version modifiée de la ressource.
Cette question a une meilleure réponse ici aux webmasters pile-site d'échange.
plus d'information, qui est également cité dans le lien ci-dessus, est sur httpwatch
selon l'article:
il existe un certain nombre de situations dans lesquelles Internet Explorer doit vérifier si une entrée mise en cache est valide:
- L'entrée du cache n'a pas de date d'expiration et le contenu est accessible pour la première fois dans une session de navigateur
- l'Entrée mise en cache a une date d'expiration mais elle a expiré
-
l'Utilisateur a demandé une mise à jour de la page en cliquant sur le bouton Actualiser ou en appuyant sur F5
entrez le code ici