Magazine Graphisme

Recharger le cache CSS ou JS à chaque mise à jour des fichiers

Publié le 31 octobre 2008 par Daxlebo

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 !


Retour à La Une de Logo Paperblog

LES COMMENTAIRES (1)

Par site Des Geeks et des lettres
posté le 13 décembre à 22:43
Signaler un abus

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)

A propos de l’auteur


Daxlebo 16 partages Voir son profil
Voir son blog

l'auteur n'a pas encore renseigné son compte l'auteur n'a pas encore renseigné son compte