web-dev-qa-db-fra.com

Générations de production de mise en cache de navigateur VueJS /

J'ai une application VueJS. Chaque fois que je lance npm run build, il crée un nouvel ensemble de fichiers dist/*; cependant, lorsque je les charge sur le serveur (après avoir supprimé l'ancienne version) et que j'ouvre la page dans le navigateur, il charge l'ancienne version (du cache, je suppose). Lorsque je rafraîchit la page, le nouveau code ne charge pas de problème.

Ceci est mon 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>

Est-il possible de le forcer à charger un nouveau code à chaque fois ou (idéalement) de vérifier si les anciens fichiers ont disparu du serveur, puis d'actualiser le navigateur?

12
ierdna

Nous avons eu des difficultés avec ce même problème et avons constaté que les navigateurs de certaines personnes ne tireraient même pas la dernière version à moins d'être actualisés manuellement. Nous avons eu des problèmes avec la mise en cache à différentes couches, y compris le CDN où nous hébergions des fichiers.

Nous avons également eu du mal à conserver les versions et à être en mesure de redéployer rapidement une version précédente en cas de problème.

Notre solution (utilisant un projet basé sur vue-cli Webpack):

1) Nous construisons la distribution pour avoir un dossier spécifique à la version au lieu de 'statique'. Cela nous aide également à suivre les générations et à «annuler» un déploiement si nécessaire. Pour changer le répertoire 'statique', changez 'assetsSubDirectory' sous 'build' dans index.js et remplacez 'assetsPublicPath' par votre chemin CDN.

2) Nous utilisons Webpack Assets Manifest pour créer un fichier manifest.json pointant vers tous les actifs. Notre manifeste inclut un hachage de tous les fichiers, en tant qu’application de haute sécurité.

3) Nous téléchargeons le dossier versionné (contenant les fichiers js et css) sur notre CDN.

4) (Facultatif) Nous hébergeons un fichier index.html dynamique sur le serveur principal. Les liens vers la feuille de style et les scripts sont renseignés par le serveur principal à l'aide d'un système de modèle extrait des données du fichier manifest.json (voir le point 5). Ceci est facultatif car vous pouvez utiliser l'option force-reload comme dans le commentaire ci-dessous, qui n'est pas une expérience géniale mais qui fonctionne.

5) Pour publier une nouvelle version, nous publions le fichier manifest.json sur le serveur principal. Nous faisons cela via un noeud final GraphQL mais vous pouvez manuellement placer le fichier json quelque part. Nous la stockons dans la base de données et l'utilisons pour renseigner le fichier index.html. Nous l'utilisons également pour vérifier les fichiers à l'aide du hachage de fichier (pour valider notre CDN n'a pas été piraté). 

Résultat: mises à jour immédiates et possibilité simple de suivre et de modifier vos versions. Nous avons constaté que la nouvelle version serait immédiatement intégrée à la plupart des navigateurs de tous les utilisateurs.

Un autre bonus: nous construisons une application qui requiert une sécurité élevée et hébergeant le fichier index.html sur notre backend (déjà sécurisé) nous a permis de réussir plus facilement nos audits de sécurité.


Modifier le 17/02/19

Nous avons constaté que les réseaux d'entreprise effectuaient la mise en cache du proxy, malgré des en-têtes sans cache. IE 11 semble également ignorer les en-têtes de cache. Ainsi, certains utilisateurs ne recevaient pas les versions les plus récentes.

Nous avons un version.json qui est incrémenté/défini au moment de la construction. Le numéro de version est inclus dans le fichier manifest.json. Le lot de construction est automatiquement téléchargé sur S3. Nous passons ensuite le fichier manifest.json au backend (nous le faisons sur une page d'entrée dans la zone Admin). Nous définissons ensuite la version "active" sur cette interface utilisateur. Cela nous permet de changer facilement les versions. 

Le serveur place la "currentVersion" comme en-tête de réponse pour toutes les demandes. Si currentVersion! == version (telle que définie dans version.json), nous demandons à l'utilisateur de cliquer pour actualiser son navigateur (plutôt que de le forcer).

5
For the Name

Basé sur cette réponse complète sur les en-têtes de cache , votre meilleur pari sera de résoudre ce problème côté serveur si vous en avez le contrôle, car tout élément des balises <meta> sera remplacé par les en-têtes définis par le serveur.

Les commentaires sur la question indiquent que vous utilisez cette application avec nginx. En utilisant la réponse liée ci-dessus, j'ai pu définir les en-têtes Cache-Control, Expires et Pragma pour toutes les demandes de fichiers se terminant par .html dans ma configuration nginx:

server {

  ...other config

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

Cela force le navigateur à demander le dernier index.html lors de chaque rechargement de page, mais il utilise toujours les ressources mises en cache (js/css/fonts/images), à moins que la dernière réponse HTML ne contienne de nouvelles références.

0
Sean Ray