web-dev-qa-db-fra.com

flask ne voit pas de changement dans le fichier .js

J'ai apporté une modification à l'un des fichiers .js Que j'utilise et quoi que je fasse, flask insiste pour extraire de la mémoire cache la dernière version du fichier , sans le changement.

Pour clarifier, j'ai la structure suivante. Tout commence par foo.html

return render_template foo.html

foo.html A un formulaire à l'intérieur qui appelle flask avec des données, puis renvoie un deuxième modèle bar.html:

return render_template bar.html

Ce deuxième modèle appelle un fichier .js, Placé dans le dossier static, mais il ne se met pas à jour lorsque le code change.

Je mentionne la structure ci-dessus parce que si le fichier .js Était placé sur foo.html Au lieu de bar.html, Alors Flask voudrais = Prenez les nouvelles modifications dans le fichier, mais dans bar.html Flask les ignore complètement.

Qu'est-ce qui se passe?

La seule chose qui a fonctionné a été de cliquer sur "désactiver le cache" sur le navigateur et de recharger à nouveau.

37
elelias

En fin de compte, il s’agit d’un problème de cache du navigateur frustrant, qui peut être résolu en forçant le navigateur à effectuer une "actualisation à chaud", qui sera une frappe au clavier/système d’exploitation, mais généralement cela fonctionne:

  • Windows: Ctrl + F5
  • Mac: Cmd + Shift + R
  • Linux: Ctrl + Maj + R

Il existe d'autres astuces de nom de fichier que l'on peut utiliser pour éviter ce problème (mentionné dans les commentaires de l'OP). Celles-ci sont particulièrement importantes en production où vous n’avez aucun contrôle sur le comportement du navigateur.

Pour les réponses non statiques Flask vous pouvez définir le cache_control.max_age propriété, qui doit indiquer au navigateur quand expirer la réponse si elle est mise en cache. Par exemple, si vous avez un noeud final XHR qui retourne des données JSON Flask), vous pouvez le faire:

@app.route('/_get_ajax_data/')
def get_ajax_data():
    data = {"hello": "world"}
    response = jsonify(data)
    response.cache_control.max_age = 60 * 60 * 24  # 1 day (in seconds)
    return response

En règle générale, vous pouvez également définir des valeurs par défaut dans la configuration de votre serveur Web de production pour des types de ressources spécifiques (CSS/JS/HTML/JSON/etc., par exemple).

Edit 4/1/2019 (sans lien avec le jour du poisson d'avril)

  • La frappe sur Mac/Safari semble maintenant être: Cmd + Opt + R (via des commentaires, merci!).
  • Voir la nouvelle réponse de @MarredCheese pour une "astuce de nom de fichier" très élégante pour forcer le navigateur à ignorer les copies en cache des fichiers mis à jour.
54
abigperson

Si vous servez vos actifs statiques avec Flask (c'est généralement le cas dans un environnement de développement), vous devrez peut-être définir le SEND_FILE_MAX_AGE_DEFAULT valeur de configuration :

Durée de contrôle du cache par défaut maximale à utiliser avec send_static_file() (gestionnaire de fichiers statique par défaut) et send_file(), en tant que datetime.timedelta Ou en secondes. Remplacez cette valeur fichier par fichier à l'aide de la fonction get_send_file_max_age() hook Flask ou Blueprint, respectivement). La valeur par défaut est 43200 (12 heures).

La solution peut être aussi simple que de mettre à jour le dictionnaire app.config, Comme ceci:

app = Flask(__name__)
...
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0

Si vous faites cela, votre navigateur ne mettra pas en cache les actifs statiques fournis par Flask.

12
YellowShark

La mise en cache est normalement bonne , il n'est donc pas recommandé de l'éliminer complètement. Et en utilisant control + F5 ou quoi que ce soit de faire une actualisation matérielle n'est évidemment pas une solution évolutive puisque vous devez le faire dans tous les navigateurs sur tous les ordinateurs.

Une meilleure idée est de laissez les navigateurs mettre en cache les fichiers la plupart du temps, mais pas juste après leur mise à jour. Vous pouvez y parvenir en ajoutant l'heure de la dernière mise à jour du fichier source sous forme d'argument. à son URL de chemin. Pour des raisons de simplicité, vous pouvez utiliser l'heure de modification la plus récente pour tous les fichiers du dossier statique (ou de tous les sous-dossiers), au lieu de consulter chaque fichier individuellement.

Python

def dir_last_updated(folder):
    return str(max(os.path.getmtime(os.path.join(root_path, f))
               for root_path, dirs, files in os.walk(folder)
               for f in files))

@app.route('/my-site')
def my_site():
    return render_template('my-site.html',
                           last_updated=dir_last_updated('mydir/static'))

Jinja Template

<script type="text/javascript" src="/static/my-script.js?u={{ last_updated }}"></script>

Résultat HTML

<script type="text/javascript" src="/static/my-script.js?u=1547330602.31"></script>
8
MarredCheese