115 votes

L'application Angular doit vider le cache après un nouveau déploiement

Nous avons une application Angular 6. Elle est servie sur Nginx. Et SSL est activé.

Lorsque nous déployons de nouveaux codes, la plupart des nouvelles fonctionnalités fonctionnent bien mais pas pour certains changements. Par exemple, si les développeurs front-end mettent à jour la connexion au service et la déploient, les utilisateurs doivent ouvrir une fenêtre de navigation privée ou vider le cache pour voir la nouvelle fonctionnalité.

Quel type de changements ne sont pas mis à jour automatiquement? Pourquoi sont-ils différents des autres?

Quelle est la solution commune pour éviter le problème?

197voto

Joel Joseph Points 1354

Le problème est que lorsqu'un fichier statique est mis en cache, il peut être stocké pendant de très longues périodes avant d'expirer. Cela peut être gênant dans le cas où vous mettez à jour un site, car la version mise en cache du fichier est stockée dans les navigateurs de vos visiteurs, ils peuvent donc être incapables de voir les modifications apportées.

Cache-busting résout le problème du cache du navigateur en utilisant un identifiant de version de fichier unique pour indiquer au navigateur qu'une nouvelle version du fichier est disponible. Par conséquent, le navigateur ne récupère pas l'ancien fichier dans le cache mais fait plutôt une demande au serveur d'origine pour le nouveau fichier.

Angular cli résout ce problème en fournissant un drapeau --output-hashing pour la commande de construction.

Vérifiez la documentation officielle : https://angular.io/cli/build

Exemple (anciennes versions)

ng build --prod --aot --output-hashing=all

Voici les options que vous pouvez passer dans --output-hashing

  • none: aucun hachage effectué
  • media: ajouter des hachages uniquement aux fichiers traités via les chargeurs [url|file]
  • bundles: ajouter des hachages uniquement aux bundles de sortie
  • all: ajouter des hachages à la fois aux médias et aux bundles

Mises à jour

Pour la nouvelle version d'Angular (par exemple, Angular 10), la commande est désormais mise à jour :

ng build --prod --aot --outputHashing=all

2 votes

Cela fonctionne. Merci pour la solution. Pourriez-vous s'il vous plaît expliquer quelles situations pourraient causer le problème? Comme je l'ai mentionné, le problème ne se produit pas avec toutes les mises à jour.

0 votes

@zhangjinzhou a mis à jour la réponse avec explication, veuillez la marquer comme réponse si cela vous aide

1 votes

Merci pour l'explication!

25voto

Alejo JM Points 366

Pour moi ajouter :

    ng build --aot --output-hashing=all

aux commandes de construction n'est pas suffisant, lorsque vous avez votre application derrière un CDN et une bonne configuration de cache nginx.

1- La première chose était de supprimer le cache pour les fichiers html (nginx) :

    location ~ \.(html)$ {
        add_header Pragma "no-cache";
        add_header Cache-Control "no-store";
        add_header strict-transport-security "max-age=31536000";
        add_header X-Frame-Options "SAMEORIGIN";
        try_files $uri $uri/ /index.html;
    }

pour les fichiers statiques (js/css ...) laisser le cache fonctionner (performances réseau / utilisabilité) :

    location ~ \.(css|htc|less|js|js2|js3|js4)$ {
        expires 31536000s;
        add_header Pragma "public";
        add_header Cache-Control "max-age=31536000, public";
        try_files $uri $uri/ /index.html;
    }

2- Laisser les versions de développement/production exactement les mêmes, à des fins de test. La commande de construction finale pour le développement :

    ng build --env=dev --aot=true --output-hashing=all --extract-css=true 

3- Nous avons besoin à chaque déploiement que le navigateur client charge tous les fichiers JavaScript depuis le serveur et non depuis le cache, même si le déploiement était une mise à jour mineure. Il semble que Angular ait quelques bugs à ce sujet : https://github.com/angular/angular-cli/issues/10641 et c'est arrivé pour moi.

J'ai fini par utiliser la puissance de bash, voici mes scripts pour supprimer le cache à chaque développement (prod/dev) en utilisant le fichier package.json :

"scripts": {
 ...
    "deploy_dev": "ng build --env=dev --aot=true --output-hashing=all --extract-css=true && npm run add_date",
    "deploy_prd": "ng build --prod && npm run add_date",
    "add_date": "npm run add_date_js && npm run add_date_css && npm run rm_bak_files",
    "add_date_js": "for i in dist/*; do if [ -f $i ]; then LC_ALL=C sed -i.bak 's:js\":js?'$(date +%H%M%m%d%y)'\":g' $i; fi done",
    "add_date_css": "sed -i.bak 's:css\":css?'$(date +%H%M%m%d%y)'\":g' dist/index.html",
    "rm_bak_files": "find dist -name '*.bak' -exec rm -Rf {} \\;"
},

explications des commandes :
add_date_js : trouver et remplacer tous les fichiers "js" par "js?{date+%H%M%m%d%y}"
add_date_css : trouver et remplacer dans dist/index.html "css" par "css?{date+%H%M%m%d%y}"
rm_bak_files : supprimer tous les fichiers .bak (performances réseau)

Ces commandes sed fonctionnent à la fois sur GNU/BSD/Mac.

liens :
Angular - Prod Build not generating unique hashes
sed in-place flag that works both on Mac (BSD) and Linux
RE error: illegal byte sequence on Mac OS X
Inline if shell script
How to loop over files in directory and change path and add suffix to filename
Is it possible to build separate CSS file with angular-cli?

0 votes

Avez-vous des commandes pour l'invite de commandes Windows ?

0 votes

Isaac, je n'ai pas de Win, mais tu peux facilement créer un docker pour le faire.

0 votes

@AlejoJM, Je sais.. cette réponse est assez ancienne. Mais le script pour renommer les fichiers javascript ne fonctionne pas. Ne renomme aucun fichier! s'exécute en silence

16voto

KMJungersen Points 105

Alors que la réponse acceptée ci-dessus fonctionnera, cet ajustement doit être effectué dans angular.json, sous configurations => \=> outputHashing => définir à all (pour les environnements de production).

Exemple simplifié:

{
  "projects": {
    "": {
      "architect": {
        "build": {
          "configurations": {
            "": {
              "outputHashing": "all"
            }
          }
        }
      }
    }
  }
}

Et comme mentionné dans ledit post, les options disponibles pour cette configuration sont les suivantes:

  • none: aucun hachage effectué
  • media: ajoute uniquement des hachages aux fichiers traités via les chargeurs [url|file]
  • bundles: ajoute uniquement des hachages aux bundles de sortie
  • all: ajoute des hachages à la fois aux médias et aux bundles

1 votes

Pour plus d'informations sur l'utilisation des environnements Angular, consultez cette page dans la documentation

7 votes

Cela est déjà fait mais ne semble toujours pas fonctionner.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X