2010-03-11 4 views
31

Il s'agit d'une application Web qui sert des images. Puisque la même requête retournera toujours la même image, je veux que les navigateurs accédant mettent en cache les images aussi agressivement que possible. Je veux à peu près dire au navigateurDemander aux navigateurs de mettre en cache de la manière la plus agressive possible

Voici votre image. Allez-y et gardez-le. ça ne va vraiment pas changer pour les deux prochains jours. Pas besoin de revenir. Vraiment. Je promets.

que je fais, à ce jour, mis

Cache-Control: public, max-age=86400 
Last-Modified: (some time ago) 
Expires: (two days from now)

et bien sûr retourner un 304 not modified si la demande a l'en-tête If-Modified-Since appropriée.

Y at-il autre chose que je puisse faire (ou quoi que ce soit que je devrais faire différemment) pour faire passer mon message dans les navigateurs?

L'application est hébergée sur Google App Engine, au cas où cela serait important.

+5

Si ça ne va pas changer, une heure d'expiration de 1 jour (* max-age *) n'est pas tant que ça. – Gumbo

+0

@Gumbo: True; comme je l'ai noté sur la réponse de Sripathi Krishnan, cela va certainement être augmenté. Je me demande toujours pourquoi Gravatar le met à 5 minutes seulement. – balpha

+0

Vous pouvez changer votre gravatar, donc c'est logique. –

Répondre

12

Vous pouvez être intéressé à vérifier l'article Google Code suivant:

En un mot, tous les navigateurs modernes devraient être en mesure de mettre en cache vos images de façon appropriée conformément aux instructions, avec les En-têtes HTTP.

+1

C'est une lecture intéressante; Merci. – balpha

1

.htaccess Essayez comme

<ifmodule mod_gzip.c> 
    mod_gzip_on Yes 
    mod_gzip_dechunk Yes 
    mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$ 
    mod_gzip_item_include handler ^cgi-script$ 
    mod_gzip_item_include mime ^text/.* 
    mod_gzip_item_include mime ^application/x-javascript.* 
    mod_gzip_item_exclude mime ^image/.* 
    mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.* 
</ifmodule> 

<ifmodule mod_deflate.c> 
AddType application/x-compress .Z 
AddType application/x-gzip .gz .tgz 
AddType application/x-httpd-php .php 
AddType application/x-httpd-php .php3 
AddOutputFilterByType DEFLATE text/html 
AddOutputFilterByType DEFLATE text/plain 
AddOutputFilterByType DEFLATE text/xml 
AddOutputFilterByType DEFLATE application/x-httpd-php 
AddOutputFilterByType DEFLATE application/x-javascript 
</ifmodule> 

<ifmodule mod_expires.c> 
    ExpiresActive On 
    ExpiresDefault "access plus 1 seconds" 
    ExpiresByType text/html "access plus 1 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 216000 seconds" 
    ExpiresByType application/x-javascript "access plus 216000 seconds" 
</ifmodule> 

<ifmodule mod_headers.c> 
    <filesMatch "\\.(ico|pdf|flv|jpg|jpeg|png|gif|swf)$"> 
    Header set Cache-Control "max-age=2592000, public" 
    </filesmatch> 
    <filesMatch "\\.(css)$"> 
    Header set Cache-Control "max-age=604800, public" 
    </filesmatch> 
    <filesMatch "\\.(js)$"> 
    Header set Cache-Control "max-age=216000, private" 
    </filesmatch> 
    <filesMatch "\\.(xml|txt)$"> 
    Header set Cache-Control "max-age=216000, public, must-revalidate" 
    </filesmatch> 
    <filesMatch "\\.(html|htm|php)$"> 
    Header set Cache-Control "max-age=1, private, must-revalidate" 
    </filesmatch> 
</ifmodule> 
+0

L'application est sur Google App Engine; il n'y a pas de '.htaccess' (ou d'Apache, d'ailleurs) – balpha

+0

Oups j'ai négligé cela. Quoi qu'il en soit, je le garde pour que cela puisse aider ceux qui ont Apache. –

10

Vous pouvez faire mieux. Les 304 sont toujours une requête/réponse HTTP. Bien que l'image ne soit pas téléchargée à nouveau, la latence peut être fatale.

Si vous pouvez inclure un identificateur de version dans vos noms d'image, vous pouvez définir l'âge maximal sur 2 ans. De cette façon, vous empêchez 304s. Si l'image change, vous mettez à jour l'identifiant de la version, ce qui change le nom du fichier. Cela garantit que le navigateur émettra une nouvelle demande.

Il nécessite des modifications à la structure de votre projet. L'identificateur de version peut être le numéro de révision SVN lors de la dernière mise à jour de l'image et peut être généré automatiquement lors de la génération. Vous aurez également besoin de mettre à jour le code HTML, donc si vous avez un mappage logique entre le nom de l'image et le chemin de l'image, votre travail sera plus facile.

Les images étant rarement mises à jour, vous pouvez également suivre une approche manuelle si vous ne pouvez pas automatiser ce que j'ai décrit ci-dessus. L'astuce consiste à ajouter uniquement de nouvelles images, ne jamais les modifier.

+0

Ce sont de bonnes idées. Le long max-age est quelque chose que je vais définitivement faire. Bien que je pense avoir lu qu'une année est le maximum autorisé selon la RFC. L'identifiant de version est quelque chose que j'ai pensé, mais malheureusement ce n'est pas une option. L'application ne sert que les images à inclure dans d'autres pages Web (pensez comme Gravatar). – balpha

+0

@Sripathi Krishnan: mais la latence meurtrière semble ne pouvoir être évitée! Le navigateur fait à nouveau des requêtes HTTP pour les images même en utilisant 'mod_expires' quand vous fermez le navigateur et l'ouvrez à nouveau sur la même page. Il ne télécharge pas l'image après la réponse du serveur, mais il s'enquiert encore du serveur, ce qui augmente la latence. Voyez ma question peut-être vous avez une idée: http: // stackoverflow.com/questions/10048740/stop-browser-to-make-http-demande-pour-images-qui-devrait-rester-cache-mod-expi –

+0

Selon la section 14.21 de rfc2616, "les serveurs HTTP/1.1 NE DEVRAIENT PAS envoyer Expires dates plus d'un an dans le futur. " une année est votre max. –

2

Il est une valeur très importante en-tête de cache que vous ne l'avez pas mentionné ici:

"post-check = 900, pré-check = 3600"

Lire cet article à ce sujet (et chercher plus):

http://www.rdlt.com/cache-control-post-check-pre-check.html

+4

C'est intéressant, merci. Quelques choses valent la peine d'être mentionnées: Ceci est seulement IE, le lien que vous liez à lui-même est lié à un article assez ancien, et je ne trouve aucune mention de votre réclamation "vos clients demandent toujours ..."; Au contraire, dans les fils de commentaires, il y a de nombreuses indications que IE respecte les en-têtes standard. – balpha

+0

Peut-être est-ce seulement par exemple, je ne sais pas. Ce que je sais, c'est que je vois sur google chrome, et mozilla firefox, sur les outils de développement, qu'à partir du moment où je place cette valeur, j'arrête d'avoir tout le temps, les images. La vérité est que je travaille vite, et après je vois que cela fonctionne mieux, je ne l'ai pas vérifié trop profondément. Peut-être qu'à l'intérieur du code source de chrome il y a un vrai ansewr si ces valeurs sont utilisées ou non. – Aristos

+0

Je supprime le "Avec cet en-tête, les navigateurs de vos clients demandent toujours vos pages et images même si vous avez défini les en-têtes que vous mentionnez." parce que je n'ai pas vérifié pour soure. J'ai également trouvé cet article relatif. http://www.google.com/support/forum/p/Chrome/thread?tid=384b6abc105a67e5&hl=en – Aristos

2

Je ne sais pas e Cela aidera au-delà des solutions proposées par d'autres, mais vous pouvez utiliser les fonctionnalités HTML5 offline web apps pour demander plus explicitement au navigateur de stocker une copie locale.

+0

C'est une bonne idée. Cela n'aidera pas dans mon cas (parce que je ne sers que les images, je ne contrôle pas le HTML des pages qui incluent ces images). Mais bon à savoir pour le cas général. +1 – balpha

1

Vous pourrait ajouter une représentation ETag pour chaque image, puis le comparer à l'en-tête If-None-Match sur les demandes entrantes (voir « Why isn’t my custom delivered image caching in the browser? »). Ceci est redondant lorsque vous utilisez l'en-tête préféré Last-Modified et c'est juste une autre façon de dire 304 de toute façon. (Je pense que GAE le fait automatiquement pour les fichiers statiques, pas sûr cependant.)

Gravatar définit très vieux Last-Modified dates - la valeur par défaut semble être "Mer, 11 Jan 1984 08:00:00 GMT". L'expiration de 5 minutes amène les navigateurs à rechercher fréquemment des images mises à jour. En d'autres termes, je pense qu'ils invitent les 304, sans essayer de convaincre les navigateurs d'utiliser simplement le cache local. Leurs têtes ressemblent à ceci:

Date: Sat, 20 Mar 2010 07:52:43 GMT 
Last-Modified: Wed, 11 Jan 1984 08:00:00 GMT 
Expires: Sat, 20 Mar 2010 07:57:43 GMT 
Cache-Control: max-age=300 

La grande différence est la date d'expiration - vous voulez deux jours, ils veulent cinq minutes. Donc, si vous voulez que les navigateurs utilisent simplement l'image mise en cache pendant 48 heures, faites ce que vous faites, seulement Cache-Control: max-age=172800 (86400 est de 24 heures).

1

L'ancienneté de l'antémémoire de quelques jours est très faible. Vous devriez le définir à un an ou même plus. Bien sûr, cela peut poser des problèmes lorsque l'image change, mais vous pouvez résoudre ce problème en ajoutant un numéro de version à l'image et en changeant la page qui référence l'image pour inclure le chemin vers la nouvelle image.

j'ai écrit plus sur la mise en cache des applications web ici: http://patchlog.com/web/7-methods-to-cache-web-applications/

+0

Vous plaisantez? Je suis tout pour le bénéfice du doute et j'apprécie toujours les conseils ou l'aide que les gens me donnent dans leurs réponses. Mais écrire à peu près la même chose que Sripathi Krishnan a fait il y a plus d'une semaine (juste avec plus de détails) seulement pour créer un lien vers votre article de blog pertinent - que j'appelle spam. – balpha

+0

Cela peut être difficile à croire, mais je n'ai pas vu sa réponse avant de poster. Et aussi mon post a plus d'idées sur la mise en cache, mais bien sûr, il est plus simple de rejeter quelque chose et de simplement voter au lieu de lire un article plutôt long. –

+0

Croyez-le ou non, le downvote n'est pas le mien. Pourtant, votre article de blog (que je ne trouve pas long du tout, le texte lié à la réponse acceptée est beaucoup plus long) n'a rien à voir avec mon problème. – balpha

Questions connexes