Флажок не видит изменения в файле .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 полностью игнорирует их.
Что происходит?
Единственное, что сработало, - это нажать "отключить кеш" в браузере и снова перезагрузить.
Ответы
Ответ 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>