Подтвердить что ты не робот

Флажок не видит изменения в файле .js

Я внес изменения в один из файлов .js, который я использую, и независимо от того, что я делаю, колба настаивает на сборе, из кэша памяти, последней версии файла без изменений.

Чтобы уточнить, у меня есть следующая структура. Все начинается с foo.html

return render_template foo.html

foo.html имеет внутреннюю форму, которая вызывает колбу с некоторыми данными, а затем возвращает второй шаблон bar.html:

return render_template bar.html

Этот второй шаблон вызывает некоторый файл .js, помещенный в папку static, но он не обновляется при изменении кода.

Я упоминаю структуру выше, потому что если файл .js был помещен на foo.html вместо bar.html, тогда Flask будет отображать новые изменения в файле. Но в bar.html Flask полностью игнорирует их.

Что происходит?

Единственное, что сработало, - это нажать "отключить кеш" в браузере и снова перезагрузить.

4b9b3361

Ответ 1

В конечном счете это проблема разочаровывающего кэша браузера, которая может быть решена путем принудительного выполнения браузером "жесткого обновления", которое будет зависеть от нажатия клавиши браузера/ОС, но обычно это работает:

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

Есть и другие хитрости с именами файлов, которые можно использовать, чтобы избежать этой проблемы (упоминается в комментариях к ОП). Это особенно важно в производстве, где вы не можете контролировать поведение браузера.

Для cache_control.max_age ответов Flask вы можете установить свойство cache_control.max_age, которое должно сообщать браузеру, когда истечет срок действия ответа, если он кэшируется. Например, если у вас есть конечная точка Flask XHR, которая возвращает данные JSON, вы можете сделать это:

@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/и т.д.)

Изменить 04/1/2019 (не имеет отношения к апрельскому дураку)

  • Клавиши для Mac/Safari теперь выглядят так: Cmd + Opt + R (через комментарии, спасибо!).
  • Смотрите новый ответ от @MarredCheese для очень элегантного "трюка с именем файла", чтобы заставить браузер игнорировать кэшированные копии для обновленных файлов.

Ответ 2

Если вы используете статические ресурсы с помощью Flask (как правило, это происходит в среде разработки), вам может потребоваться установить SEND_FILE_MAX_AGE_DEFAULT конфигурации SEND_FILE_MAX_AGE_DEFAULT:

Максимальный возраст send_static_file() управления кэшем по умолчанию для использования с send_static_file() (статический обработчик файлов по умолчанию) и send_file(), в качестве datetime.timedelta или в виде секунд. Переопределите это значение для каждого файла, используя get_send_file_max_age() для Flask или Blueprint, соответственно. По умолчанию 43200 (12 часов).

Решить это можно так же просто, как обновить словарь app.config, например так:

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

Если вы это сделаете, ваш браузер не будет кэшировать статические ресурсы, которые обслуживает Flask.

Ответ 3

Кэширование, как правило, хорошо, поэтому не рекомендуется полностью его устранять. И использование control + F5 или чего-либо еще для жесткого обновления, очевидно, не является масштабируемым решением, поскольку вы должны делать это в каждом браузере на каждом компьютере.

Лучшая идея - позволить браузерам кэшировать файлы большую часть времени, но не сразу после их обновления. Этого можно добиться, добавив время, когда исходный файл последний раз обновлялся в качестве аргумента, к его URL-адресу пути. Для простоты вы можете использовать самое последнее время изменения для любого файла в статической папке (или любых подпапках), в отличие от просмотра каждого файла в отдельности.

питон

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>