1148 Stimmen

So zwingen Sie den Browser, zwischengespeicherte CSS- und JavaScript-Dateien neu zu laden

Ich habe festgestellt, dass einige Browser (insbesondere Firefox und Oper ) sind sehr eifrig bei der Verwendung von zwischengespeicherten Kopien von .css y .js Dateien, auch zwischen Browser-Sitzungen. Dies führt zu einem Problem, wenn Sie eine dieser Dateien aktualisieren, der Browser des Benutzers aber weiterhin die im Cache gespeicherte Kopie verwendet.

Wie kann man den Browser des Benutzers am elegantesten dazu zwingen, die Datei neu zu laden, wenn sie sich geändert hat?

Im Idealfall würde die Lösung den Browser nicht dazu zwingen, die Datei bei jedem Besuch der Seite neu zu laden.


Ich habe gefunden John Millikin's y da5id's Vorschlag als nützlich erweisen. Es stellt sich heraus, dass es dafür einen Begriff gibt: Auto-Versionierung .

Ich habe unten eine neue Antwort veröffentlicht, die eine Kombination aus meiner ursprünglichen Lösung und Johns Vorschlag ist.

Eine weitere Idee, die von SCdF wäre, einen falschen Abfrage-String an die Datei anzuhängen. (Ein Python-Code, der den Zeitstempel automatisch als gefälschte Abfragezeichenfolge verwendet, war eingereicht von pi. .)

Es gibt jedoch eine Diskussion darüber, ob der Browser eine Datei mit einem Abfrage-String in den Cache einspeichern würde oder nicht. (Zur Erinnerung: Wir wollen, dass der Browser die Datei zwischenspeichert und bei zukünftigen Besuchen verwendet. Wir wollen nur, dass er die Datei erneut abruft, wenn sie sich geändert hat.)

493voto

Kip Punkte 102702

Diese Lösung ist in PHP geschrieben, aber sie sollte leicht an andere Sprachen angepasst werden können.

Das Original .htaccess regex kann zu Problemen mit Dateien wie json-1.3.js . Die Lösung besteht darin, nur umzuschreiben, wenn am Ende genau 10 Ziffern vorhanden sind. (Denn 10 Ziffern decken alle Zeitstempel vom 9.9.2001 bis zum 20.11.2286 ab.)

Zunächst verwenden wir die folgende Rewrite-Regel in .htaccess:

RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]

Nun schreiben wir die folgende PHP-Funktion:

/**
 *  Given a file, i.e. /css/base.css, replaces it with a string containing the
 *  file's mtime, i.e. /css/base.1221534296.css.
 *
 *  @param $file  The file to be loaded.  Must be an absolute path (i.e.
 *                starting with slash).
 */
function auto_version($file)
{
  if(strpos($file, '/') !== 0 || !file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
    return $file;

  $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
  return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $file);
}

Ändern Sie nun Ihr CSS an den Stellen, an denen Sie es einfügen:

<link rel="stylesheet" href="http://stackoverflow.com/css/base.css" type="text/css" />

Zu diesem:

<link rel="stylesheet" href="<?php echo auto_version('/css/base.css'); ?>" type="text/css" />

Auf diese Weise müssen Sie den Link-Tag nie wieder ändern, und der Benutzer sieht immer das neueste CSS. Der Browser kann die CSS-Datei zwischenspeichern, aber wenn Sie Änderungen an Ihrem CSS vornehmen, sieht der Browser dies als eine neue URL, so dass er nicht die zwischengespeicherte Kopie verwendet.

Dies kann auch mit Bildern, Favicons und JavaScript funktionieren. Im Grunde alles, was nicht dynamisch erzeugt wird.

229voto

keparo Punkte 32084

Einfache Client-seitige Technik

Im Allgemeinen ist Caching gut... Es gibt also mehrere Techniken, je nachdem, ob Sie das Problem für sich selbst bei der Entwicklung einer Website beheben oder ob Sie versuchen, den Cache in einer Produktionsumgebung zu kontrollieren.

Die allgemeinen Besucher Ihrer Website werden nicht die gleichen Erfahrungen machen wie Sie, wenn Sie die Website entwickeln. Da der durchschnittliche Besucher Ihre Website seltener besucht (vielleicht nur ein paar Mal im Monat, es sei denn, Sie sind ein Google- oder Hi5-Netzwerk), ist es unwahrscheinlicher, dass er Ihre Dateien im Cache hat, und das könnte schon ausreichen.

Wenn Sie eine neue Version im Browser erzwingen wollen, können Sie immer einen Query-String zur Anfrage hinzufügen und die Versionsnummer erhöhen, wenn Sie größere Änderungen vornehmen:

<script src="/myJavascript.js?version=4"></script>

Dadurch wird sichergestellt, dass jeder die neue Datei erhält. Es funktioniert, weil der Browser anhand der URL der Datei feststellt, ob er eine Kopie im Cache hat. Wenn Ihr Server nicht so eingestellt ist, dass er etwas mit der Abfragezeichenfolge macht, wird sie ignoriert, aber der Name sieht für den Browser wie eine neue Datei aus.

Wenn Sie hingegen eine Website entwickeln, möchten Sie nicht jedes Mal die Versionsnummer ändern, wenn Sie eine Änderung an Ihrer Entwicklungsversion speichern. Das wäre mühsam.

Ein guter Trick bei der Entwicklung Ihrer Website wäre also, automatisch einen Query-String-Parameter zu generieren:

<!-- Development version: -->
<script>document.write('<script src="/myJavascript.js?dev=' + Math.floor(Math.random() * 100) + '"\><\/script>');</script>

Das Hinzufügen eines Query-Strings zur Anfrage ist ein guter Weg, um eine Ressource zu versionieren, aber für eine einfache Website kann dies unnötig sein. Und denken Sie daran: Caching ist eine gute Sache.

Es ist auch erwähnenswert, dass der Browser nicht unbedingt geizig ist, wenn es darum geht, Dateien im Cache zu speichern. Browser verfügen über entsprechende Richtlinien, und sie halten sich in der Regel an die in der HTTP-Spezifikation festgelegten Regeln. Wenn ein Browser eine Anfrage an einen Server stellt, ist ein Teil der Antwort eine Abgelaufen Header... ein Datum, das dem Browser mitteilt, wie lange es im Cache gehalten werden soll. Wenn der Browser das nächste Mal eine Anfrage für dieselbe Datei erhält, sieht er, dass er eine Kopie im Cache hat, und schaut in der Abgelaufen Datum, um zu entscheiden, ob es verwendet werden soll.

Ob Sie es glauben oder nicht, es ist tatsächlich Ihr Server, der den Browser-Cache so beständig macht. Sie könnten Ihre Servereinstellungen anpassen und die Abgelaufen Kopfzeilen, aber die kleine Technik, die ich oben geschrieben habe, ist wahrscheinlich ein viel einfacherer Weg für Sie, dies zu tun. Da die Zwischenspeicherung gut ist, möchten Sie dieses Datum in der Regel weit in die Zukunft setzen (ein "Far-future Expires Header") und die oben beschriebene Technik verwenden, um eine Änderung zu erzwingen.

Wenn Sie an weiteren Informationen über HTTP oder darüber, wie diese Anfragen gestellt werden, interessiert sind, empfehlen wir Ihnen das Buch "High Performance Web Sites" von Steve Souders. Es ist eine sehr gute Einführung in das Thema.

115voto

Leopd Punkte 39216

Google's mod_pagespeed Plugin für Apache übernimmt die automatische Versionierung für Sie. Das ist wirklich raffiniert.

Es parst HTML auf dem Weg aus dem Webserver (funktioniert mit PHP, Ruby on Rails Python, statisches HTML - alles) und schreibt Links zu CSS-, JavaScript- und Bilddateien so um, dass sie einen ID-Code enthalten. Die Dateien werden unter den geänderten URLs mit einer sehr langen Cache-Kontrolle bereitgestellt. Wenn sich die Dateien ändern, werden die URLs automatisch geändert, so dass der Browser sie erneut abrufen muss. Im Grunde funktioniert es einfach, ohne dass Sie Ihren Code ändern müssen. Es wird sogar Ihren Code auf dem Weg nach draußen zu minify.

99voto

levik Punkte 108445

Anstatt die Version manuell zu ändern, würde ich empfehlen, einen MD5-Hash der eigentlichen CSS-Datei zu verwenden.

Ihre URL würde also etwa so lauten

http://mysite.com/css/[md5_hash_here]/style.css

Sie könnten immer noch die Rewrite-Regel verwenden, um den Hash zu entfernen, aber der Vorteil ist, dass Sie jetzt Ihre Cache-Richtlinie auf "Cache für immer" einstellen können, denn wenn die URL dieselbe ist, bedeutet das, dass die Datei unverändert ist.

Sie können dann ein einfaches Shell-Skript schreiben, das den Hash der Datei berechnet und Ihr Tag aktualisiert (Sie sollten es wahrscheinlich in eine separate Datei verschieben, um es aufzunehmen).

Führen Sie das Skript einfach bei jeder CSS-Änderung aus, und Sie sind fertig. Der Browser lädt Ihre Dateien NUR neu, wenn sie geändert werden. Wenn Sie eine Änderung vornehmen und diese dann rückgängig machen, müssen Sie nicht erst herausfinden, zu welcher Version Sie zurückkehren müssen, damit Ihre Besucher sie nicht erneut herunterladen müssen.

99voto

Phantom007 Punkte 1979

Ich bin mir nicht sicher, warum Sie sich so viel Mühe geben, diese Lösung zu implementieren.

Sie müssen lediglich den Änderungszeitstempel der Datei abrufen und ihn als Querystring an die Datei anhängen.

In PHP würde ich das so machen:

<link href="mycss.css?v=<?= filemtime('mycss.css') ?>" rel="stylesheet">

filemtime() ist eine PHP-Funktion, die den Zeitstempel der Dateiänderung zurückgibt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X