Browsercache HTML-Dateien

baserider

Well-known member
ID: 174417
L
10 März 2007
682
23
Hi,

per PHP und mod_rewrite werden dynamisch HTML-Dateien generiert bzw. gibt es auch ein paar statische HTML-Dateien.
In alle Dateien habe ich ein Javascript eingebunden, was aber (bei mir in Chrome) erst wirksam wurde, nach dem ich den Cache geleert hatte. DEr normale User soll ja nicht erst den Cache leeren. Gibt es da Möglichkeiten, wie ich das kontrollieren kann?

Die einzelnen CSS-Dateien z.B. sind schon mit einer Art Versionsnummer eingebunden, damit nach jeder Änderung immer die aktuelle Datei geladen wird.
 
Hi,

damit kann ich dann generell für jeden user den cache ein bzw. ausschalten oder? Gut wäre ja, wenn der User die Seite gesehen hat, und dann wird der Cache aktiv. So ähnlich wie bei der Versionierung der einzubundenden Dateien.
 
damit kann ich dann generell für jeden user den cache ein bzw. ausschalten oder?
Nö.
Du kannst dem User-Agent nur sagen, ob die angeforderte Resource gecacht werden darf oder nicht. Kein User-Agent auf der Welt erlaubt dir, seine Einstellungen (so er überhaupt welche besitzt) zu verändern.
Gut wäre ja, wenn der User die Seite gesehen hat, und dann wird der Cache aktiv.
:?: Ein User-Agent kann wohl nix cachen, was er nicht mindestens einmal abgerufen hat, oder was meinst du? :biggrin:
 
hmm.. ich erklärs mal an nem beispiel:

ich habe in einer externen Javascript-Datei eine neue Funktion eingefügt. Die Funktion rufe ich auf der Seite auf. Leider wird sie nicht ausgeführt, ausser ich lösche den Cache. Die js-Datei ist hinten mit einem Parameter versehen, aber ich denke der Browser holt die alte Seite (ohne eingefügte JS-Funktion). Das würde ich gern ändern
 
Du kannst jedenfalls nicht beeinflussen, ob ein Browser überhaupt bei dir nachfragt, ob es eine veränderte Datei gibt. Theoretisch könnte ein Browser auch über Jahre mit eine einmal geladene Datei für seinen Benutzer anzeigen, ohne jemals wieder bei dir nachzufragen.

Einzige Stellschraube ist die Headermanipulation, um ein Ablaufdatum in nicht allzu weiter Zukunft zu legen (z.B. 1 Woche oder auch mal 1 Tag). Je kürzer die Zeit ist, desto mehr wird das Cacheprinzip natürlich torpediert und die Netzwerklast würde steigen. Aber das ist für die Browser ja eh kein Zwang, die können z.B. ohnehin sagen, dass sie frühestens nach einer Woche wieder nachfragen, selbst wenn von dir eine kürzere Zeit gefordert wird.

So ganz bin ich bisher aber auch noch nicht durchgestiegen, wann Browser eine neue Netzwerkanfrage ausführen. Trotz identischer Headerdaten bezüglich Lebenszeit werden bei meinem Firebug manchmal trotzdem Anfragen angezeigt, wo eigentlich (noch) gar keine sein sollten und auch bei einem Hardrefresh manchmal keine, wo eigentlich was sein sollte.

Wichtig ist letztlich nur, dass zusammenhängende Dateien, also CSS, JS oder Bilder in Verbindung mit ihrer jeweiligen HTML/PHP-Datei dem gleichen Stand entsprechen. Und dafür gibt es effektiv nur eineinhalb Möglichkeiten. Entweder anghängte Parameter oder "neue" Dateinamen. Aber beides ist nicht ganz ideal. Ersteres mag z.B. auch PageSpeed nicht. UNd zweiteres weil dann theoretisch beim Browser mit der Zeit viele alte Dateistände angesammelt werden, die eigentlich nur ersetzt werden müssten (was natürlich nicht geschieht, wenn die Dateinamen voneinander abweichen).

Ich nehme aber folgende Lösung: Anfragen an CSS, JS und Bilder werden per htaccess auf eine zentrale php geleitet (eine zweite neben der eigentlichen Seitenanfrage "index.php"). CSS und JS werden noch aus verschiedenen Unterordnern zusammengebastelt und komprimiert (Kommentare und Leerzeilen löschen etc.). Die Ergebnisse werden auf dem Server auch noch mal zwischengespeichert, damit diese Berechnungen nur bei Datumsänderung der Quelldateien neu durchgeführt werden müssen - genau wie das HTML-Ergebnis der anderen Datei, das sich nur bei Änderungen am Template oder der Daten in der Datenbank ändert. In der Regel werden also diese gecachten Dateien ausgeliefert.

Und dabei kann eben auch leicht das Prinzip für abweichende Dateinamen eingearbeitet werden, da diese Schnittstelle einfach Namensbestandteile ignorieren kann. So könnte sowohl bei template_11111.css als auch bei template_22222.css auf die immer gleich lautende Datei template.css zugegriffen werden. Ob das nun fortlaufende Zahlen sind oder z.B. ein Hash des Änderungsdatums oder sonstewas ist ja völlig egal. Aber nur dann kann man sich sicher sein, dass eine neue html-Ausgabe, die eine neue js oder css-Version benötigt auch die Anfrage auf eben jene geänderte js/css auslöst.

Aber wie gesagt: Ideal ist eigentlich alles nicht. Irgendwelche Kompromisse gibt es bei sowas immer.
 
Die js-Datei ist hinten mit einem Parameter versehen, aber ich denke der Browser holt die alte Seite (ohne eingefügte JS-Funktion).
Mit diesem Trick kann der Browser gar nicht mehr cachen. Obige Posts bezogen sich darauf, dass sich eine Resource ändert, während die URL gleichbleibt. Ändert sich die URL, so kann der User-Agent gar nichts aus dem Cache laden, weil für ihn die Resource völlig unbekannt ist.

https://example.com/foo.js?v=1 ist eine völlig andere Resource wie https://example.com/foo.js?v=2.

Guck dir nur mal das Forum hier an: Stell dir vor, ein Browser würde h**p://www.klamm.de/forum/showthread.php?t=42 cachen und beim Aufruf von h**p://www.klamm.de/forum/showthread.php?t=4711 den falschen Thread zeigen. Undenkbar 8O

Was du also hast, ist eine Browser-Fehlfunktion. Da kannst du als Webprogrammierer nix dagegen machen. Maximal kann sich der User zur Not behelfen, indem er ungültige Cacheeinträge löscht oder mit einer Neuinstallation den Browser "bereinigt".
Was is das denn für ein komischer Browser, der sich da so verhält?
 
Mit diesem Trick kann der Browser gar nicht mehr cachen. Obige Posts bezogen sich darauf, dass sich eine Resource ändert, während die URL gleichbleibt. Ändert sich die URL, so kann der User-Agent gar nichts aus dem Cache laden, weil für ihn die Resource völlig unbekannt ist.

Genau, so will ich es auch, aber in diesem Fall ist es ja die eingebundene Javascript-Datei (oder eben CSS). Ich meinte dann den Aufruf der jeweiligen HTML-Datei, in der diese Dateien eingebunden sind.

Manipulation per header hatte ich auch gesehen, aber das soll ja auch nicht so zuverlässig sein:

header("Cache-Control: max-age=3600, must-revalidate");

Also mir ist es im Firefox und Chrome aufgefallen. Erst wenn ich ein par mal aktualisiert habe geht es dann.
 
Genau, so will ich es auch, aber in diesem Fall ist es ja die eingebundene Javascript-Datei (oder eben CSS). Ich meinte dann den Aufruf der jeweiligen HTML-Datei, in der diese Dateien eingebunden sind.
Jetzt blick ich nimmer durch.

In Post #1 sagst du, die JS-Datei wird gecacht. Jetzt isses die Datei, die die JS-Datei einbindet? Was nun?

Caching der JS/CSS-Datei verhinderst du mit einem Parameter (ggf. +HTTP-Header).
Caching der HTML-Datei verhindert du nur mit HTTP-Header (theoretisch kannst du auch Parameter verwenden, aber das wird hässlich).

HTTP-Header hast du Cache-Control, Last-Modified/If-Modified-Since(im Request), Expires, E-Tag/If-None-Match(im Request), die dir helfen können.
 
Ich rede die ganze Zeit von ner HTML Datei und das mit den eingebundenen Ressourcen war nur ne Zusatzinfo, wie ich es eben bei eingebundenen Dateien mit dem Cache mache. Das geht aber nicht für die aufgerufenen Dateien, in welcher diese Ressourcen eingebunden sind. (ok, man könnte das mit unterchiedlichen Dateinamen machen, aber das ist keine option für mich)

Mittels header und Cache-Control hatte ich ja vorhin auch geschrieben, aber da hieß es ja in einem Post weiter oben, das es auch nicht so zuverlässig ist, was ich ebenfalls auch im Netz lesen konnte.
 
Die einfachste (und nervenschonendste) Variante ist die Versionierung, die Du ja scheinbar auch schon bei den CSS-Dateien verwendest. Nenn die Datei doch bspw. script-v1.js und zähl das bei jeder einzelnen Änderung hoch.

Kann man auch dynamisch per mod_rewrite anpassen (versionsweise cachen, wenn Version X noch nicht vorhanden, erzeugen und abspeichern). Die jeweiligen Versionen kannst Du dann auch mit entsprechenden Expires-Headern versehen, dass sie lange im Cache liegen bleiben. Durch die Änderung des Dateinamens sollte sichergestellt sein, dass der Client immer die aktuellste Version erhält...

[edit]

Grad erst bewusst gelesen, dass die Version mit der Dateinamensänderung für Dich nicht in Frage kommt. Gibt's dafür 'nen Grund? Immerhin machst Du's doch scheinbar bei den CSS-Dateien auch?
 
Mittels header und Cache-Control hatte ich ja vorhin auch geschrieben, aber da hieß es ja in einem Post weiter oben, das es auch nicht so zuverlässig ist, was ich ebenfalls auch im Netz lesen konnte.
Zuverlässig is nix zu 100%. Es ist schließlich das Programm des Benutzers, was die Webseiten downlädt, rendert und anzeigt. Wenn jemand seinen User-Agent manipuliert, dass er sich nicht an die Protokolle und Standards hält, dann hast du als Webprogrammierer einfach Pech gehabt.
 
Das der Browser .css und .js - Dateien cached ist gut! Das soll er auch machen!

Wie schon von thehacker beschrieben: wenn du einen nichtsnutzigen Parameter dranhängst, sollte der Browser von sich aus die Resource neu laden
.../script.js?v=1
.../script.js?v=2.
Ansonsten würde ich sagen: ist doch egal! Nach ein paar Seitenaufrufen, läd der Browser sowieso die Resourcen-Dateien noch ein mal neu.