47 votes

Mise en cache des images de sites web avec Apache

Comment puis-je faire en sorte que le contenu statique d'Apache soit {mise en cache par le navigateur} et non {vérifié à chaque requête} ?

Je travaille sur un site web hébergé sur un serveur Apache. Récemment, je testais quelque chose avec les en-têtes (Content-Type pour différents types de contenu) et j'ai vu beaucoup de demandes conditionnelles pour des images. Exemple :

200 /index.php?page=1234&action=list
304 /favicon.ico
304 /img/logo.png
304 /img/arrow.png
(etc.)

Bien que les fichiers d'image soient des contenus statiques et qu'ils soient mis en cache par le navigateur, chaque fois qu'un utilisateur ouvre une page qui contient un lien vers eux, ils font l'objet d'une demande conditionnelle, à laquelle ils répondent par "304 Not Modified". C'est une bonne chose (moins de données transférées), mais cela signifie plus de 20 requêtes supplémentaires à chaque chargement de page (chargement de page plus long en raison de tous ces allers-retours, même avec Keep-Alive et pipelining activés).

Comment puis-je dire au navigateur de conserver le fichier existant et de ne pas vérifier s'il existe une version plus récente ?

EDIT : la méthode mod_expires fonctionne, même avec le favicon.

62voto

Piskvor Points 46986

Expiration : d'Apache résout ce problème

a2enmod expires

il doit être chargé dans la configuration du serveur, et configuré dans le fichier .htaccess (ou dans la configuration du serveur).

Avec un Expiration : la ressource n'est demandée que la première fois. Avant la date d'expiration, les demandes suivantes sont satisfaites à partir du cache du navigateur. Une fois que le délai spécifié a expiré et que la ressource est nécessaire, c'est seulement à ce moment-là qu'elle est redemandée (sous condition - un 304 sera renvoyé pour une ressource inchangée). Le seul moyen fiable d'effacer la ressource du cache avant qu'elle n'expire est de le faire manuellement ou en forçant un rafraîchissement (généralement Ctrl-F5). (Cela peut poser un problème si la ressource change entre-temps, mais les images statiques ne changent pas très souvent).

# enable the directives - assuming they're not enabled globally
ExpiresActive on

# send an Expires: header for each of these mimetypes (as defined by server)
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"

# css may change a bit sometimes, so define shorter expiration
ExpiresByType text/css "access plus 1 days"

Pour favicon.ico, un peu plus de travail est nécessaire (Apache ne reconnaît normalement pas les fichiers d'icônes Windows, et les envoie en tant que text/plain par défaut).

# special MIME type for icons - see http://www.iana.org/assignments/media-types/image/vnd.microsoft.icon
AddType image/vnd.microsoft.icon .ico
# now we have icon MIME type, we can use it
# my favicon doesn't change much
ExpiresByType image/vnd.microsoft.icon "access plus 3 months"

Et voilà, ça marche™ !

1 votes

J'ai spécifié que mon favicon devait avoir un type MIME de "image/x-icon" - et je n'arrive pas à faire en sorte qu'Apache définisse les en-têtes Expires sur celui-ci. Savez-vous pourquoi ? Dois-je utiliser image/vnd.microsoft.icon ?

1 votes

@Tom : "Le type MIME officiel enregistré par l'IANA pour les fichiers .ICO est image/vnd.microsoft.icon." (Wikipedia) Donc, vous n'avez pas besoin de l'utiliser, mais c'est le type MIME correct - enverriez-vous "image/x-jpg" avec des images JPEG au lieu du standard "image/jpeg" ? Y a-t-il une raison technique pour laquelle vous ne voulez pas renvoyer le type MIME correct ?

1 votes

@Tom : pour ce qui est de la première question, le serveur ne devrait pas se soucier du type MIME, du moment qu'il le connaît. Avez-vous AddType avant ExpiresByType pour ce type MIME ?

34voto

Marco Demaio Points 8667

Avec le filesMatch au lieu de la directive ExpiresByType vous pouvez regrouper Content-Type par appariement subtype (par exemple image/* ), au lieu d'énumérer chaque type/subtype paire, pas subtype (par exemple image/jpeg , image/png ).

#Set caching on image files for 11 months
<filesMatch "\.(ico|gif|jpg|png)$">
  ExpiresActive On
  ExpiresDefault "access plus 11 month"
  Header append Cache-Control "public"
</filesMatch>

D'après cet article de Google J'ai fait en sorte que l'expiration ne dépasse pas 1 an ( access plus 11 month ) et ajouté Cache-Control "public" pour activer la mise en cache HTTPS pour Firefox.

Pour les CSS et JS, Google recommande un délai d'expiration d'une semaine.

<filesMatch "\.(css|js)$">
  ExpiresActive On
  ExpiresDefault "access plus 1 week"
  Header append Cache-Control "public"
</filesMatch>

1 votes

J'aime beaucoup cette réponse. Merci de la partager !

0 votes

Si j'ai besoin de vérifier '<IfModule mod_headers.c>', est-il possible d'avoir une directive imbriquée ?

3voto

ConroyP Points 24021

Si vous définissez le Expires sur votre réponse http pour vos images statiques, votre serveur ne sera pas vérifié à nouveau pour cette image après le premier téléchargement jusqu'à ce que le temps spécifié soit écoulé, par exemple si je télécharge maintenant un fichier sur votre serveur qui donne son en-tête Expires l'en-tête comme

Expires: Fri, 1 Jan 2010 00:00:01 GMT 

mon navigateur ne le recherchera plus sur votre serveur jusqu'en 2010, à moins que je ne vide mon cache ou que je ne fasse un rafraîchissement forcé (Ctrl+F5 sous Windows).

Il existe une introduction simple à la mise en place de ce système. ici et une liste d'autres réponses potentiellement utiles à l'adresse suivante wikipedia

2voto

Anon Points 11

En ce qui concerne favicon.ico, mettez-le dans le document Root de votre serveur, disons /var/www/html, et ajoutez ceci à /etc/httpd/conf/httpd.conf dans la section Alias :-.

Alias /favicon.ico "/var/www/html/favicon.ico"
<Directory "/var/www/html">
    <Files favicon.ico>
       ExpiresActive On
       ExpiresDefault "access plus 1 month"
    </Files>
</Directory>

Un seul favicon.ico fonctionnera alors pour tous les sites hébergés virtuels puisque vous lui attribuez un alias. Après qu'un utilisateur ait visité votre site, toute visite ultérieure puisera dans la copie du cache du navigateur pendant un mois, et non sur le web.

Je n'ai pas pu obtenir

ExpiresByType image/ico "access plus 1 month"

pour fonctionner. Peut-être doit-il être de type text/plain comme suggéré ci-dessus. Dans tous les cas, ExpiresDefault fonctionne correctement.

0 votes

Bon point pour la favicon globale, si cela ne vous dérange pas que tous les sites partagent la même. Voir ma réponse concernant image/ico : 1) image/ico n'est pas le type MIME correct, 2) vous devez définir image/vnd.microsoft.icon - il n'est pas prédéfini par Apache.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X