web-dev-qa-db-de.com

Erstellung von VueJS/Browser-Caching

Ich habe eine VueJS-App. Immer, wenn ich npm run build ausführt, wird ein neuer Satz von dist/*-Dateien erstellt. Wenn ich sie jedoch auf den Server lade (nach dem Löschen des alten Builds) und die Seite im Browser öffne, wird der alte Build geladen (vom Cache ausgehend). Wenn ich die Seite aktualisiere, lädt der neue Code kein Problem.

Das ist meine index.html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
        <meta http-equiv="cache-control" content="max-age=0" />
        <meta http-equiv="cache-control" content="no-cache" />
        <meta http-equiv="expires" content="-1" />
        <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
        <meta http-equiv="pragma" content="no-cache" />
        <link rel="stylesheet" href="/static/css/bootstrap.min.css"/>
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>

Gibt es eine Möglichkeit, es jedes Mal zu zwingen, neuen Code zu laden, oder (im Idealfall) zu überprüfen, ob die alten Dateien vom Server verschwunden sind, und dann den Browser zu aktualisieren?

12
ierdna

Wir hatten Probleme mit dem gleichen Problem und fanden heraus, dass die Browser einiger Benutzer die neueste Version nicht einmal verwenden würden, wenn sie nicht manuell aktualisiert wurden. Wir hatten Probleme mit dem Caching auf verschiedenen Ebenen, einschließlich des CDNs, auf dem wir Dateien gehostet haben.

Wir hatten auch Schwierigkeiten mit der Pflege von Versionen und der Möglichkeit, eine frühere Version schnell erneut bereitzustellen, wenn etwas schief geht.

Unsere Lösung (mit einem auf vue-cli Webpack basierenden Projekt):

1) Wir erstellen die Distribution so, dass sie einen versionsspezifischen Ordner anstelle von 'static' hat. Dies hilft uns auch dabei, Builds nachzuverfolgen und eine Bereitstellung bei Bedarf rückgängig zu machen. Um das 'statische' Verzeichnis zu ändern, ändern Sie 'assetsSubDirectory' unter 'build' in index.js und ändern Sie 'assetsPublicPath' in Ihren CDN-Pfad.

2) Wir verwenden Webpack Assets Manifest , um eine manifest.json-Datei zu erstellen, die auf alle Assets verweist. Unser Manifest enthält einen Hash aller Dateien, da es sich um eine Hochsicherheitsanwendung handelt.

3) Wir laden den versionierten Ordner (mit den js und css) auf unser CDN hoch.

4) (Optional) Wir hosten eine dynamische index.html-Datei auf dem Backend-Server. Die Links zum Stylesheet und zu den Skripts werden vom Backend-Server mithilfe eines Vorlagensystems gefüllt, das aus den Daten in der manifest.json (siehe # 5) abgerufen wird. Dies ist optional, da Sie die Option "Force-Reload" wie in dem Kommentar unten verwenden können. Dies ist keine großartige Erfahrung, funktioniert jedoch.

5) Um eine neue Version zu veröffentlichen, stellen wir die manifest.json auf dem Backend-Server bereit. Wir machen dies über einen GraphQL-Endpunkt, aber Sie können die Json-Datei manuell an eine andere Stelle setzen. Wir speichern dies in der Datenbank und verwenden es, um die index.html aufzufüllen, und um Dateien anhand des Datei-Hashes zu überprüfen (um zu überprüfen, ob unser CDN nicht gehackt wurde). 

Ergebnis: Sofortige Updates und die einfache Möglichkeit, Ihre Versionen zu verfolgen und zu ändern. Wir haben festgestellt, dass die neue Version in fast allen Browsern der Benutzer sofort angezeigt wird.

Ein weiterer Bonus: Wir entwickeln eine Anwendung, die hohe Sicherheit erfordert. Durch das Hosting der index.html auf unserem (bereits gesicherten) Backend konnten wir unsere Sicherheitsüberprüfungen leichter bestehen.


Edit 17.02.19

Wir fanden heraus, dass Unternehmensnetzwerke Proxy-Caching trotz Header ohne Cache durchführen. IE 11 scheint auch Cache-Header zu ignorieren. Daher haben einige Benutzer nicht die aktuellsten Versionen erhalten.

Wir haben eine version.json, die zur Erstellungszeit inkrementiert/definiert wird. Die Versionsnummer ist in manifest.json enthalten. Das Build-Bundle wird automatisch in S3 hochgeladen. Wir übergeben dann die manifest.json an das Backend (dies tun wir auf einer Einstiegsseite im Admin-Bereich). Wir setzen dann die "aktive" Version auf dieser Benutzeroberfläche. Dadurch können wir Versionen leicht ändern/wiederherstellen. 

Das Backend setzt die "currentVersion" als Antwortheader für alle Anforderungen. Wenn die Version currentVersion! == (wie in version.json definiert), bitten wir den Benutzer, auf zu klicken, um seinen Browser zu aktualisieren (anstatt ihn zu erzwingen).

5
For the Name

Um den Cache zu löschen, kannst du rm -rf node_modules/.cache

Dies löscht Ihren Cache. Sie können vor der Bereitstellung einen neuen Build ausführen.

Ich hatte das gleiche Problem, als ich eine Produktionserstellung ausführte, aber selbst wenn mein Code lokal ausgeführt wurde, zeigte er auf die Produktionserstellung anstatt auf meine letzten Änderungen.

Ich glaube, dies ist ein verwandtes Problem: https://github.com/vuejs/vue-cli/issues/245

2
Connor Leech

Basierend auf dieser umfassenden Antwort auf Cache-Header wird Ihre beste Wette dies auf der Serverseite sein, wenn Sie die Kontrolle darüber haben, da alles in den <meta>-Tags von den vom Server festgelegten Headern überschrieben wird.

Die Kommentare zu der Frage zeigen an, dass Sie diese App mit nginx bereitstellen. Mit der obigen Antwort oben konnte ich die Header Cache-Control, Expires und Pragma für alle Anforderungen für Dateien festlegen, die mit .html auf diese Weise in meiner Nginx-Konfiguration enden:

server {

  ...other config

  location ~* \.html?$ {
    expires -1;
    add_header Pragma "no-cache";
    add_header Cache-Control "no-store, must-revalidate";
  }
}

Dies zwingt den Browser erfolgreich zum Anfordern des neuesten index.html bei jedem Neuladen der Seite. Die zwischengespeicherten Elemente (js/css/fonts/images) werden jedoch weiterhin verwendet, sofern in der neuesten HTML-Antwort keine neuen Verweise vorhanden sind.

0
Sean Ray