web-dev-qa-db-ja.com

flaskは.jsファイルの変更を認識しません

使用する.jsファイルの1つに変更を加え、何をしても、flaskはメモリキャッシュからファイルの最後のバージョンを取得することを主張し、変更なし。

明確にするために、私は次の構造を持っています。すべてはfoo.htmlで始まります

return render_template foo.html

foo.htmlには、flask=いくつかのデータを呼び出してから2番目のテンプレートbar.htmlを返すフォームがあります:

return render_template bar.html

この2番目のテンプレートは、staticフォルダーに配置された.jsファイルを呼び出しますが、コードが変更されても更新されません。

.jsファイルがfoo.htmlの代わりにbar.htmlに置かれた場合、Flask wouldピックアップファイルの新しい変更。ただし、bar.html Flaskでは、それらは完全に無視されます。

何が起こっている?

唯一機能したのは、ブラウザの「キャッシュを無効にする」をクリックして、再度リロードすることでした。

37
elelias

最終的にこれはイライラするブラウザキャッシュの問題であり、ブラウザに「ハードリフレッシュ」を強制することで解決できます。これはブラウザ/ OSに依存するキーストロークになりますが、一般にこれは機能します。

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

この問題を回避するために使用できる他のファイル名のトリックがあります(OPのコメントに記載されています)。これらは、ブラウザの動作を制御できない本番環境で特に重要です。

非静的Flask応答の場合、cache_control.max_ageプロパティ。キャッシュされている場合、応答の有効期限をブラウザに通知する必要があります。たとえば、JSONデータを返すFlask XHRエンドポイントがある場合、これを行うことができます。

@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

通常、特定のリソースタイプ(CSS/JS/HTML/JSON/etcなど)の運用Webサーバー設定でデフォルト値を設定することもできます

編集4/1/2019(エイプリルフールとは無関係)

  • Mac/Safariのキーストロークは、Cmd + Opt + Rのようになりました(コメント経由で、ありがとう!)。
  • @MarredCheeseからの新しい回答を参照して、更新されたファイルのキャッシュされたコピーをブラウザーに無視させる非常にエレガントな「ファイル名のトリック」を確認してください。
54
abigperson

Flask(これは通常開発環境の場合です)を使用して静的アセットを提供している場合、 _SEND_FILE_MAX_AGE_DEFAULT_構成値

_datetime.timedelta_または秒として、send_static_file()(デフォルトの静的ファイルハンドラー)およびsend_file()で使用するデフォルトのキャッシュ制御最大経過時間。それぞれFlaskまたはBlueprint)のget_send_file_max_age()フックを使用して、ファイルごとにこの値をオーバーライドします。デフォルトは43200(12時間)です。

これを解決するには、次のように_app.config_辞書を更新するだけです。

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

これを行うと、ブラウザはFlaskによって提供される静的アセットをキャッシュしません。

12
YellowShark

キャッシングは通常は良好であるため、完全に削除することはお勧めできません。そして使用 control + F5 または、ハードリフレッシュを実行するものは、すべてのコンピューターのすべてのブラウザーで実行する必要があるため、明らかにスケーラブルなソリューションではありません。

より良いアイデアは、ブラウザがほとんどの時間ファイルをキャッシュするようにしますが、更新された直後ではありませんソースファイルが最後に更新された時間を引数として追加することでこれを達成できますパスURLへ。簡単にするために、各ファイルを個別に見るのではなく、静的フォルダー(またはサブフォルダー)内のファイルに対して最新の変更時間を使用できます。

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'))

ジンジャテンプレート

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

HTML結果

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