Gestion du cache du navigateur dans les applications à page unique

27

J'essaie de comprendre comment gérer correctement le cache du navigateur Web pour les applications à page unique.

J'ai une conception assez typique: plusieurs fichiers HTML, JS et CSS implémentant le SPA, et un tas de données JSON consommées par le SPA. Des problèmes surviennent lorsque je souhaite effectuer une mise à jour: je mets à jour la partie statique du site et le code qui génère le JSON en même temps, mais les navigateurs clients ont souvent la partie statique mise en cache, donc l'ancien code essaie de traiter les nouvelles données et peut (en fonction des modifications apportées) rencontrer des problèmes. (En particulier, IE semble plus agressif que Chrome ou Firefox à propos de l'utilisation de JS en cache sans revalidation.)

Quelle est la meilleure façon de gérer cela?

  1. Assurez-vous que mes modifications JSON sont rétrocompatibles et supposez que les caches du navigateur expireront dans un délai raisonnable.
  2. Incorporez une sorte de numéro de version dans le JS statique et le JSON, puis exécutez-les window.location.reload(true);s'ils ne correspondent pas.
  3. Déterminez la combinaison appropriée d'en-têtes ( must-revalidateou no-cacheautre); les sources varient selon la façon de procéder) pour garantir que les navigateurs revalident toujours toutes les ressources à chaque chargement, même si cela signifie quelques allers-retours supplémentaires pour charger le site.
  4. Micro-gérer mon contrôle de cache et expire les en-têtes afin que le contenu statique expire lorsque je veux pousser une mise à jour.
  5. Autre chose?
Josh Kelley
la source
1
J'ai entendu des échecs inattendus # 3 et # 4 dans les contrôles du navigateur Web intégré si votre environnement est mauvais ( toux iOS) de collègues. # 1 et # 2 peuvent être un choix au niveau de l'application, mais peuvent toujours (?) Provoquer des problèmes de cache pour d'autres ressources ou des chargements partiels de ressources. La seule chose que j'ai vu fonctionner de manière fiable dans du code prêt pour la production est de récupérer yoururl.html? <SomeTimeStamp> car cela supprimera la plupart des mécanismes de mise en cache. Bonus: intégrez l'intégralité de votre application Web dans un fichier afin que les chargements réussissent ou échouent atomiquement. Inconvénient: fonctionne mieux sur un lien local. Votre kilométrage peut varier. Bonne chance!
J Trana
2
+1 à l'utilisation d'un numéro de version ou d'un horodatage comme paramètre d'URL pour les ressources.
9000

Réponses:

14

Vous avez besoin d'une solution de contournement du cache . Le rôle de la suppression du cache est le suivant:

  1. Renommez les ressources en un nom unique en fonction de leur contenu.
  2. Mettez à jour toutes les références à ces ressources.

Dans un projet basé sur Grunt, il est courant d'utiliser grunt-rev pour garantir que tous les fichiers qui doivent être actualisés reçoivent des noms uniques, en fonction de leur contenu.

Si vous vous assurez que vos fichiers JSON obtiennent des noms de fichiers contournant le cache avec leurs références dans votre Javascript, les clients chargeront toujours les fichiers JSON attendus par Javascript.

L'avantage de la dénomination de fichiers basée sur le hachage est que les fichiers qui n'ont pas été modifiés obtiendront les mêmes noms de fichiers après le contournement du cache, afin que les navigateurs puissent continuer à utiliser en toute sécurité le contenu mis en cache lorsqu'il n'a pas changé.

De toute évidence, c'est le genre de chose que vous souhaitez automatiser dans le cadre de la construction de la production de votre projet, vous n'avez donc pas à suivre manuellement la modification des noms de fichiers et des références.

Ted Percival
la source
2
+1 pour le bit "cache busting" en italique, qui ouvre la porte à google réellement ce produit de manière productive.
Zak Kus
@Ted Percival - le framework yeoman fait cela, que j'utilise, mais je vois un problème. lorsque je publie une nouvelle version, le navigateur peut avoir le fichier index.html mis en cache avec des références aux anciens fichiers ... et le navigateur obtient une erreur. comment dois-je résoudre ce problème? (A.) créer un lien symbolique entre tous les anciens noms de fichier et les nouveaux (cela fonctionne) (B.) ajouter un en-tête sans cache à index.html (mais est-ce toujours respecté) (C.) ajouter .htaccess pour reconnaître un fichier revved et recherchez celui de base (c.-à-d. 12345.main.js -> main.js)
timh
5

Vous pouvez utiliser des en if-modified-since + last-modified- if-none-match + etagtêtes ou avec l'en- cache-controltête approprié . (Il peut y avoir des bogues de navigateur , mais rien que vous ne pouvez pas gérer dans les navigateurs récents.)

Si les fichiers sont statiques, je vous suggère de les utiliser if-modified-since, car cela peut être fait automatiquement avec un serveur HTTP bien configuré. Il devrait renvoyer 304 si le fichier n'est pas modifié depuis le dernier téléchargement.

Je ne pense pas que vos # 1 et # 2 fonctionneraient à long terme. Le # 3 ou # 4 peut fonctionner. Le n ° 3 est plus simple, mais vous ne devez apprendre à gérer ce problème qu'une seule fois. J'essaierais donc le # 4 si j'étais vous, mais la solution pourrait dépendre des navigateurs que vos clients utilisent ... Par exemple IE8 a des problèmes en mettant à jour le cache ajax, etc ...

inf3rno
la source
2

Si vous pouvez inclure le filtre de servlet Java dans votre SPA, voici une solution de travail: CorrectBrowserCacheHandlerFilter.java

Fondamentalement, lorsque votre navigateur demande les fichiers statiques, le serveur redirige toutes les demandes vers la même mais avec un paramètre de requête de hachage ( ?v=azErTpar exemple) qui dépend du contenu du fichier statique cible.

En faisant cela, le navigateur ne mettra jamais en cache les fichiers statiques déclarés dans votre index.htmlpar exemple (car il recevra toujours a 302 Moved Temporarily), mais ne mettra en cache que ceux avec la version de hachage (le serveur répondra 200pour eux). Ainsi, le cache du navigateur sera utilisé efficacement pour ces fichiers statiques avec une version de hachage.

Avertissement: je suis l'auteur de CorrectBrowserCacheHandlerFilter.java.

Anthony O.
la source