Sie sollten auf jeden Fall weitreichende Cache-Header für Ihre Assets wie CSS und JavaScript (und Bilder und Fonts und was auch immer sonst) setzen. Das sagt dem Browser: „Behalte diese Datei im Grunde für immer.“ So muss der Browser sie beim Navigieren von Seite zu Seite auf einer Website – oder beim erneuten Besuch oder Aktualisieren der Seite – nicht erneut herunterladen, was zu deutlich schnelleren Seitenladezeiten führt. Das ist für die Web-Performance enorm wichtig, also tun Sie es!
Aber wie zwingen Sie den Browser, eine frische Version der Datei zu erhalten? Nun, es gibt eine ganze Reihe von Möglichkeiten. Schauen Sie sich diesen Blogbeitrag für mehr an. Aber hier ist eine, die ich kürzlich verwendet habe und die ich dokumentieren wollte.
Der Trick ist, den Query-String zu ändern
Es gab eine Zeit, in der die vorherrschende Meinung war, dass die Änderung des Query-Strings nicht ausreicht, aber selbst dann waren die Gründe, warum es nicht funktionierte, meist Randfälle. Heutzutage ist die Änderung des Query-Strings in Ordnung (vorausgesetzt, Sie ändern das Standardverhalten nicht, Dienste wie Cloudflare lassen Sie es tun).
Also, eines Tages liefern Sie es in Ihrem HTML so aus
<link rel="stylesheet" href="style.css?v=1" />
Dann ändern Sie diesen Query-String, um den Cache zu leeren, wenn Sie es brauchen
<link rel="stylesheet" href="style.css?v=2" />
Der HTML-Teil wird übrigens entweder nicht gecached oder für eine viel kürzere Zeit gecached, sodass Änderungen am HTML gesehen werden.
Ich mache es manchmal von Hand
Viele Jahre lang habe ich den Cache auf dieser Website geleert, indem ich eine PHP-Variable gesetzt und sie verwendet habe, um Assets zu ändern, wie zum Beispiel…
<?php $ver = 1.0; ?>
<link rel="stylesheet" href="style.css?v=<?php echo $ver; ?>" />
<link rel="stylesheet" href="some-other-asset.css?v=<?php echo $ver; ?>" />
Hey, das funktioniert, aber ich habe diese Variable von Hand manipuliert. Manchmal habe ich vergessen, es zu tun, und selbst wenn ich mich erinnert habe, habe ich mich irgendwie geärgert, es tun zu müssen.
Automatisches Version-Busting mit Gulp
Ich verwende derzeit einen Gulp-gesteuerten Build-Prozess auf dieser Website, der alle klassischen Dinge erledigt: Sass, Babel, Dateiverkettung, Live-Reload…
Mir fiel auf, dass ich Gulp auch dazu bringen könnte, den Query-String zu ändern, wann immer Änderungen an CSS oder JavaScript vorgenommen werden. JavaScript hat eine .replace() Methode, und diese ist in Node/Gulp einfach mit dem gulp-replace Plugin verfügbar.
Ich erstelle eine Aufgabe. Wenn ich sie aufrufe, sucht sie in meiner Header-Datei nach dem String cache_bust= plus einem Wert und ersetzt ihn durch einen neuen zufälligen String, basierend auf Datum und Uhrzeit.
gulp.task("cache-bust-css", function() {
var cbString = new Date().getTime();
return gulp
.src(["header.php"])
.pipe(
replace(/cache_bust=\d+/g, function() {
return "cache_bust=" + cbString;
})
)
.pipe(gulp.dest("."));
});
Das Gleiche mache ich in einer separaten Aufgabe, wenn JavaScript-Dateien bearbeitet und kompiliert werden.
Es ist immer noch ein bisschen dumm
Beachten Sie, dass ich den Query-String bei allen CSS-Assets ändere, jedes Mal, wenn sich eines davon ändert. Das ist nicht so effizient, wie es sein könnte. Ich sollte wahrscheinlich nur den Query-String bei den geänderten Dateien ändern.
Ich werde es irgendwann angehen. Manchmal muss man einfach Schritt für Schritt zu besseren Lösungen gelangen.
Dies ist nur eine Methode! Es gibt weitere Gulp-Plugins speziell dafür. Andere Build-Systeme haben unterschiedliche Ansätze. Dieser Ansatz hat sich für mich und meine genauen Bedürfnisse zu der Zeit gut bewährt. Teilen Sie gerne Ihre Strategie mit!
Anstelle einer Version oder eines Datums verwenden Sie einen Hash der Datei, um den Cache zu leeren. Dadurch ändert er sich nur, wenn sich die Datei ändert.
Oder Sie könnten tatsächliche Cache-Header oder E-Tag-Header verwenden, wofür sie genau da sind. Dies in der URL zu tun, bindet HTML und CSS, sodass Sie jetzt Änderungen an beiden vornehmen müssen, um sicherzustellen, dass Benutzer die richtige Version erhalten. Einige CDNs behandeln den Query-String nicht als eindeutige URL.
Die Änderung des Query-Strings ist nicht der richtige Weg, um Caching zu handhaben.
Ich mache das buchstäblich seit einem Jahrzehnt.
Etwas lange auf eine bestimmte Weise zu tun, macht es nicht richtig.
Schauen Sie sich ETags und ihre Möglichkeiten an: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
Wahrscheinlich ist es erwähnenswert, dass dies aus der Perspektive der Datei funktioniert, nicht dessen, was sie anfordert. Vergessen Sie nicht, dass nicht alles, was Ihre Ressourcen anfordert, unter Ihrer Kontrolle steht, daher sind ETags eine Möglichkeit, die richtige Version zu liefern und die Cache-Invalidierung für alle Szenarien korrekt durchzuführen.
@Ashley Sheridan Bitte lesen Sie https://css-tricks.de/strategies-for-cache-busting-css/#article-header-id-4 und https://stackoverflow.com/a/47535993/616067 bezüglich ETags und der damit verbundenen Probleme.
Ashley,
Die Verwendung von ETags ist meiner Meinung nach Teil einer Caching-Strategie, aber bedenken Sie, dass Sie, um veraltete ETags zu identifizieren, immer noch einen Server-Trip benötigen, nur um eine 304 – Not Modified – zu erhalten. Wenn Sie garantieren können, dass die Ressource während des Builds nicht veraltet ist, ist es meiner Meinung nach besser, dies dann zu tun. File Hashing und Referenzierung (z.B. „app-1ed9ab.js“) während eines Builds ist eine sehr gute Möglichkeit, dies zu tun, oder sogar die Verwendung eines Query-Strings, wenn Sie keine fortgeschrittenere Build-Pipeline zur Verfügung haben. Dies stellt sicher, dass Sie Far-Future Expiration Caching verwenden können, bei dem der Browser nicht einmal eine Überprüfung mit dem Server benötigt.
Hallo Chris,
Schauen Sie sich die exzellenten Pakete gulp-rev und gulp-rev-replace an, die das für Sie erledigen. Wir verwenden sie seit Jahren in unserer Organisation und sie sind absolut zuverlässig für FFE-Setups mit Cache-Busting.
Prost!
Simon
Zuletzt geändert (Datum)… Das ist alles, was ich zu sagen habe. ;-)
Ehrlich gesagt wünschte ich, Chrome auf Mobilgeräten würde CSS tatsächlich aktualisieren, wenn man einen expliziten Refresh versucht (wie bei Desktop-Browsern), aber es scheint das nur als Reload zu behandeln? (und es behält das alte Stylesheet gerne über eine Woche lang, es sei denn, man greift zu Dingen wie diesem) Die einzige Möglichkeit, einen Refresh zu erzwingen, scheint das vollständige Löschen des Caches aus den Einstellungen zu sein? :/
Es ist ziemlich nervig, wenn man statische HTML-Dateien liefert (weil man nichts anderes tun kann und eine schnelle Website haben möchte), da das bedeutet, dass man alles ändern muss, nur für eine kleine Änderung am Stylesheet. Entweder das, oder nur Änderungen vornehmen, die keine kritischen Fehler verursachen, wenn sie noch nicht angewendet wurden.
In meinem Gulp- und Webpack-Setup https://github.com/jmartsch/acegulp4 in der Datei https://github.com/jmartsch/acegulp4/blob/master/gulpfile.babel.js/tasks/rev.js verwende ich gulp-rev-all und ein rev-manifest, um gehashte Dateinamen basierend auf dem Inhalt einer Datei zu generieren. Dann verwende ich eine PHP-Funktion, um die tatsächliche Version einer Bild-, CSS- oder JS-Datei zu erhalten, die geladen werden soll.
Das ist cool, ich mache das tatsächlich mit
filemtimein PHP und verwende diesen Zeitstempel, nur die Assets, die geändert wurden, erhalten ihren Query-String geändert! :)Ich bin sicher, es gibt eine viel elegantere Methode, aber auf einer einfachen Website mit nur einem Haupt-Stylesheet funktioniert das in WordPress
Ich habe einige Kommentare bezüglich Zeitstempeln gesehen, die Leute verwendet haben. Während das für Ihre Situationen funktioniert, bedenken Sie für andere Leser, dass dies möglicherweise nicht in allen Fällen funktioniert. Wir laden beispielsweise unsere Assets auf Microsoft Azure Blob Storage hoch, der dazu neigt, Zeitstempel beim Erstellen des Assets nicht zu honorieren oder zu manipulieren. Sie könnten sich in einer Situation wiederfinden, in der ein nicht geändertes Asset im Cache ungültig gemacht und anschließend neu erworben wird. Da ist das Hashing des Dateiinhalts, obwohl es vielleicht etwas mehr Arbeit ist, von Vorteil.
Hallo!
Ich mag es wirklich, das zu tun
<link rel="stylesheet" href="style.css?v=” />
@Eduard. Nun, das können Sie tun, aber das verschiebt das Problem nur an eine andere Stelle. Sie müssen sich daran erinnern, den v-Parameter von Hand zu aktualisieren, wie Chris schrieb: „Ich würde manchmal vergessen, es zu tun, und selbst wenn ich mich daran erinnerte, ärgerte ich mich irgendwie darüber.“
Sie könnten auch das Änderungsdatum der Datei verwenden, wie andere schrieben, was einen Reload verursachen könnte, auch wenn der Dateiinhalt nicht geändert wurde und das Änderungsdatum der Datei geändert wird.
Meiner Meinung nach ist Cache Busting durch gehashte Dateinamen und eine Zuweisungskarte (nämlich rev-manifest) die beste Lösung.