web-dev-qa-db-fra.com

Comment empêcher la mise en cache de la page de navigateur dans Rails

Ubuntu -> Apache -> Phusion Passenger -> Rails 2.3

La partie principale de mon site réagit à vos clics. Donc, si vous cliquez sur un lien, il vous enverra à la destination et régénérera instantanément votre page.

Mais si vous appuyez sur le bouton Précédent, vous ne voyez pas la nouvelle page. Malheureusement, cela ne se présente pas sans une actualisation manuelle; il semble que le navigateur le cache. Je veux m'assurer que le navigateur ne cache pas la page.

Séparément, je do veux définir des dates d'expiration très éloignées pour tous mes actifs statiques.

Quelle est la meilleure façon de résoudre ce problème? Devrais-je résoudre ce problème dans Rails? Apache? Javascript?

Merci pour toute votre aide, Jason


Hélas. Aucune de ces suggestions n'a forcé le comportement que je recherche.

Peut-être y a-t-il une réponse javascript? J'aurais pu Rails écrire un horodatage dans un commentaire, puis faire vérifier par javascript si les temps sont dans les cinq secondes (ou tout ce qui fonctionne). Si oui, alors d'accord, mais si non , puis rechargez la page?

Pensez-vous que cela fonctionnerait?

Merci pour votre aide,

Jason

145
Jason Butler

Enfin compris ceci - http://blog.serendeputy.com/posts/how-to-prevent-browsers-from-caching-a-page-in-Rails/ dans application_controller.rb

class ApplicationController < ActionController::Base

before_filter :set_cache_headers

  private

  def set_cache_headers
    response.headers["Cache-Control"] = "no-cache, no-store"
    response.headers["Pragma"] = "no-cache"
    response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
  end
end
322
Jason Butler
14
Sacre

J'ai utilisé cette ligne avec un certain succès dans le contrôleur. Cela fonctionne dans Safari et Internet Explorer mais je ne l'ai pas vu fonctionner avec Firefox.

response.headers["Expires"] = "#{1.year.ago}"

Pour votre deuxième point, si vous utilisez les méthodes d’aide Rails telles que

stylesheet_link_tag

et laissez les paramètres par défaut sur votre serveur Web, les actifs sont généralement assez bien mis en cache.

3
erik

La méthode la plus simple consiste à écrire un middleware Rack, qui modifie l'en-tête Cache-Control en fonction d'une logique (par exemple, uniquement pour le type mime application/xml). Ou, pour une approche plus laide, mais qui fonctionne encore, on pourrait changer la constante ActionDispatch :: Response :: DEFAULT_CACHE_CONTROL en 'no-cache'. Bien sûr, si la granularité du contrôleur et/ou de l'action est requise, il est préférable de le faire dans le contrôleur.

1
Roman

Point de note: Vous ne pouvez pas vider le cache de façon conditionnelle (comme si un before_filter appelle uniquement reset_cache _ si l'utilisateur y est déjà allé). Vous devez inconditionnellement vider le cache, car le navigateur ne fera pas une nouvelle demande simplement pour voir si cette fois-ci, il doit être rechargé, même s'il n'a pas eu besoin de la dernière fois.

Exemple:

before_filter :reset_cache, if: :user_completed_demographics?

cela ne fonctionnera pas pour empêcher les utilisateurs de revenir après leur passage, car le navigateur utilise les en-têtes de cache d'origine du bouton Précédent.

before_filter :reset_cache

fonctionnera cependant (après avoir actualisé la page et effacé le cache d’avant de l’ajouter, évidemment), car à la première demande, le navigateur obtiendra le no-cache, no-store, ... et l'appliquer aux chargements de page futurs.

1
BalinKingOfMoria