Votre site accueille des visiteurs réguliers et vous devez modifier une feuille de style CSS ou un script JS. Problème : ces fichiers sont mis en cache sur le navigateur (côté client), et les utilisateurs risquent de ne pas bénéficier des modifications avant plusieurs jours. Ou pire, pour peu que le source HTML ait changé, l'affichage sera illisible ou les fonctions totalement inutilisables ! Voici une solution simple qui ne demande qu'une ligne de PHP et se mettra à jour automatiquement par la suite.
Votre site accueille des visiteurs réguliers et vous devez modifier une feuille de style CSS ou un script JS. Problème : ces fichiers sont mis en cache sur le navigateur (côté client), et les utilisateurs risquent de ne pas bénéficier des modifications avant plusieurs jours. Ou pire, pour peu que le source HTML ait changé, l'affichage sera illisible ou les fonctions totalement inutilisables ! Voici une solution simple que j'ai testée avec succès sur IE6, Firefox et Google Chrome (Gecko). Elle ne demande qu'une ligne de PHP et se mettra à jour automatiquement par la suite.
Principe : proposer un autre fichier
Le mécanisme de mise en cache des fichiers javascript et CSS est pratique, car il limite la quantité de données à transférer depuis le serveur à chaque chargement de page. Sur certains sites riches, il permet de restreindre très nettement la bande passante nécessaire et d'accélérer l'affichage des pages. Cependant ce mécanisme pose une contrainte : dès que la durée de conservation du fichier a été spécifiée au client, celui-ci ne cherchera plus à mettre à jour les données avant expiration de cette période. Réduire la durée de conservation de ces fichiers à quelques minutes pour faire face à un éventuel changement ferait perdre l'intérêt du cache.
Puisqu'il est impossible de prévenir un client qu'un fichier a changé, une solution est de lui proposer un autre fichier dès qu'un changement a lieu. Pour cela, on peut employer deux méthodes :
Méthode laborieuse
Une des solutions consiste à renommer systématiquement le fichier à chaque changement. Ainsi, au lieu d'un fichier ecran.css
, vous chargez un fichier ecran_2008-10-31.css
. Cela est doublement contraignant. D'une part, si vous effectuez plusieurs mises à jour quotidiennes lors de pics d'activité, vous devrez trouver un système de nommage compliqué avec les heures et minutes de mise à jour. D'autre part, si vous avez plusieurs templates à gérer, vous devrez répercuter ces modifications sur chacune d'entre elles à chaque fois que vous bougez une virgule, avec la perte de temps et le risque d'erreurs que cela comporte. Bref, au cas où ce ne serait pas clair, je ne préconise pas cette méthode.
Méthode paresseuse (= rusée)
Comme souvent en informatique, paresse est mère de vertu, et la solution qui vous demandera le moins de travail à la longue est souvent préférable. Ici, on va profiter d'une subtilité des navigateurs, qui considèrent qu'une URL de fichier lié est définie non seulement par le nom du fichier (ecran.css
), mais également par les arguments qui lui sont passés (?arg=blabla
). Ainsi, le fichier ecran.css?v=1
et le fichier ecran.css?v=2
sont traités comme des fichiers différents par le navigateur, qui rechargera le cache entre l'un et l'autre, quand bien même il s'agit du même fichier sur le serveur.
Passer un nombre en argument permet de changer de version de manière simple. Il sera cependant préférable de passer une variable automatique pour ne pas avoir à incrémenter ce nombre à chaque mise à jour. C'est ici que la fonction PHP filemtime()
vient à notre rescousse. Cette fonction renvoie dans une chaîne la date et l'heure de modification d'un fichier... Vous voyez où je veux en venir ?
C'est simple : au lieu de déclarer le fichier ecran.css
, on y ajoutera un bout de code PHP qui lui passe en argument sa date de modification : <?php print filemtime('ecran.css'); ?>
. Vos inclusions de fichiers externes ressembleront donc à cela :
<html>
<head>
<script type="text/javascript" src="js/script.js?v=<?= filemtime('js/script.js'); ?>">
<link rel="stylesheet" type="text/css" href="css/ecran.css?v=<?= filemtime('css/ecran.css'); ?>">
</head>
... etc
L'effet est immédiat. Lorsque vous modifierez les fichiers ultérieurement, leur URL sera automatiquement mise à jour et le cache rechargé sur les navigateurs clients. A vous les joies de la paresse !
Débat
Il y a bien sûr un bémol, qui pourrait rendre cette technique inadaptée à grande échelle : la fonction filemtime()
impose un accès disque sur le serveur à chaque chargement de page, ce qui induit une charge supplémentaire sur le sous-système de stockage si des milliers de visiteurs fréquentent votre site simultanément. Néammoins, je pense que les serveurs modernes sont équipés de cache disque qui stockent en tampon ce type de données et évitent de stresser inutilement les composants. Quant à la compatibilité avec les navigateurs, elle n'a été vérifiée que sur un petit nombre de versions. Partagez vos expérimentations sur ce thème.
D'autres méthodes existent sûrement pour parvenir au même résultat (réécriture d'URL, gestion du cache avec PHP, que sais-je ?). Faites-nous en part !
LES COMMENTAIRES (1)
posté le 13 décembre à 22:43
Article sympathique, cependant on peut trouver d’autres configurations et astuces. Perso. j’ai trouvé les armes ultimes pour augmenter la réactivité (http://bit.ly/79fxkr)